reduxの知識を深く理解する
redux状態管理のコンテナ.
使用開始
reducer関数は動作のタイプを判断して状態を修正する必要があり,関数には戻り値が必要であることに注意する.この関数の最初のパラメータは
コンポーネントでこのように使用
コンポーネントの
bindActionCreators
react-redux
このライブラリはreactとreduxを関連付けるための接続ライブラリで、reduxを使用しているときに痛みを見つけたのは、設定状態を購読する方法で購読をキャンセルすることですが、react-reduxはpropsで自動的にこの機能を完了することができます.
コンポーネントでの使用
mapStateToProps
このパラメータは関数がオブジェクトを返す形式で、パラメータはstoreの
例えば私たちの状態はこのような
mapDispatchToProps
この方法はactionのメソッドを属性にマッピングし、パラメータは関数がオブジェクトを返す形式であり、パラメータはstoreの
現在
reduxの原理
createStoreの原理
reactとreact-reduxの2つのライブラリの使用を把握し、彼らの役割がそれぞれ何をしているかを知っています.では、原理を見て、まずreduxの原理を勉強し、
この方法の原理は,この対象のプロトタイプが
reduxには、ステータスが変化するたびにサブスクリプションを実行する関数をサブスクリプションおよびキャンセルする方法もあります.購読を発表するのは私たちがこれ以上よく知っている原理で、私はあまり言いません.
コードには、デフォルト値を得るために
bindActionCreatorsの原理
使用開始
//
const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'
//
const initState = { num: 0 }
function reducer(state = initState, action) {
switch (action.type) {
case INCREMENT:
return { num: state.num + 1 }
case DECREMENT:
return { num: state.num - 1 }
default:
return state
}
}
//
const store = createStore(reducer)
reducer関数は動作のタイプを判断して状態を修正する必要があり,関数には戻り値が必要であることに注意する.この関数の最初のパラメータは
state
状態、2番目のパラメータはaction
動作、action
パラメータはオブジェクトで、オブジェクトの中にはundefined
type
属性は、この属性に基づいて様々な動作タイプを区別する.コンポーネントでこのように使用
const actions = {
increment() {
return { type: INCREMENT }
},
decrement() {
return { type: DECREMENT }
}
}
class Counter extends Component {
constructor(props) {
super(props);
//
this.state = {
num: store.getState().num
}
}
componentDidMount() {
//
this.unsubscribe = store.subscribe(() => {
this.setState({ num: store.getState().num })
})
}
componentWillUnmount() {
//
this.unsubscribe()
}
increment = () => {
store.dispatch(actions.increment())
}
decrement = () => {
store.dispatch(actions.decrement())
}
render() {
return (
{this.state.num}
);
}
}
コンポーネントの
state
およびprops
が変更されるとビューが更新され、コンテナ内の状態が変更されるたびに変更が必要になります.state
、この場合に使用する必要がありますstore
のsubscribe
この変更ステータスを購読する方法で、このメソッドの戻り値は購読をキャンセルし、コンテナ内のステータスを変更するにはstore
のdispatch
は配布動作タイプを表し、store
のgetState
は、取得容器中の状態を示す.bindActionCreators
store.dispatch
を手動で呼び出すのを防止するために、reduxのこのbindActionCreators
メソッドを使用してdispatch
メソッドを自動的にバインドするのが一般的です.let actions = {
increment() {
return { type: INCREMENT }
},
decrement() {
return { type: DECREMENT }
}
}
actions = bindActionCreators(actions, store.dispatch)
class Counter extends Component {
constructor(props) {
super(props);
//
this.state = {
num: store.getState().num
}
}
componentDidMount() {
//
this.unsubscribe = store.subscribe(() => {
this.setState({ num: store.getState().num })
})
}
componentWillUnmount() {
//
this.unsubscribe()
}
increment = () => {
actions.increment()
}
decrement = () => {
actions.decrement()
}
render() {
return (
{this.state.num}
);
}
}
export default Counter;
react-redux
このライブラリはreactとreduxを関連付けるための接続ライブラリで、reduxを使用しているときに痛みを見つけたのは、設定状態を購読する方法で購読をキャンセルすることですが、react-reduxはpropsで自動的にこの機能を完了することができます.
import {Provider} from 'react-redux'
import {createStore} from 'redux'
const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'
const initState = { num: 0 }
function reducer(state = initState, action) {
switch (action.type) {
case INCREMENT:
return { num: state.num + 1 }
case DECREMENT:
return { num: state.num - 1 }
default:
return state
}
}
const store = createStore(reducer)
ReactDOM.render((
), document.getElementById('root'))
Provider
は高次コンポーネントであり、store属性としてstoreパラメータを入力する必要があり、高次コンポーネントは使用状態のコンポーネントを包む.これにより、コンポーネント間プロパティの転送が完了します.import {connect} from 'react-redux'
const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'
let actions = {
increment() {
return { type: INCREMENT }
},
decrement() {
return { type: DECREMENT }
}
}
class Counter extends Component {
render() {
return (
{this.props.num}
);
}
}
const mapStateToProps = state => {
return state
}
const mapDispatchToProps = actions
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
コンポーネントでの使用
connect
メソッドはコンポーネントとコンテナを関連付け、この高次関数は、2回実行する必要があり、1回目は2つのパラメータを入力する必要があり、1つ目のパラメータは状態を属性にマッピングし、2つ目はaction
は属性としてマッピングされ、2回目はパラメータとしてコンポーネントを入力する必要がある.mapStateToProps
このパラメータは関数がオブジェクトを返す形式で、パラメータはstoreの
state
で、私たちが必要とする属性をフィルタリングすることができて、コンポーネントの属性が多すぎて、維持しにくいことを防止します例えば私たちの状態はこのような
{ a: 1, b: 2 }
で、このような{ a: 1 }
に変えたいと思っています.const mapStateToProps = state => {
return { a: state.a }
}
mapDispatchToProps
この方法はactionのメソッドを属性にマッピングし、パラメータは関数がオブジェクトを返す形式であり、パラメータはstoreの
dispatch
であり、action
をフィルタリングするために使用することができる.let actions = {
increment() {
return { type: INCREMENT }
},
decrement() {
return { type: DECREMENT }
}
}
現在
action
には2つの方法がありますが、私たちは1つだけ必要であればそうすることができます.const mapDispatchToProps = dispatch => {
return {
increment: (...args) => dispatch(actions.increment(...args))
}
}
reduxの原理
createStoreの原理
reactとreact-reduxの2つのライブラリの使用を把握し、彼らの役割がそれぞれ何をしているかを知っています.では、原理を見て、まずreduxの原理を勉強し、
createStore
の方法を書きます.import createStore from './createStore'
export {
createStore
}
createStore
がどのように使用されているかを振り返ると、使用時にプロセッサreducer
関数が入力され、動作タイプに応じて状態を変更して状態に戻り、dispatch
メソッドを呼び出して状態を変更したときにのみreducer
が実行されて新しい状態が得られる.import isPlainObject from './utils/isPlainObject'
import ActionTypes from './utils/actionTypes'
function createStore(reducer, preloadedState) {
let currentState = preloadedState
function getState() {
return currentState
}
function dispatch(action) {
//
if (!isPlainObject(action)) {
throw new Error(' ')
}
//
currentState = currentReducer(currentState, action)
}
dispatch({ type: ActionTypes.INIT })
return {
dispatch,
getState
}
}
export default createStore
dispatch
メソッドを呼び出す場合、1つのオブジェクトが入力され、type
プロパティがあり、入力されたパラメータの正確性を保証するためにisPlainObject
メソッドが呼び出され、1つのオブジェクトであるか否かが判断される.function isPlainObject (obj) {
if (typeof obj !== 'object' || obj === null) {
return false
}
let proto = obj
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}
return Object.getPrototypeOf(obj) === proto
}
export default isPlainObject
この方法の原理は,この対象のプロトタイプが
Object.prototype
と等しいか否かを判断することである.reduxには、ステータスが変化するたびにサブスクリプションを実行する関数をサブスクリプションおよびキャンセルする方法もあります.購読を発表するのは私たちがこれ以上よく知っている原理で、私はあまり言いません.
function createStore(reducer, preloadedState) {
let currentState = preloadedState
let currentReducer = reducer
let currentListeners = []
let nextListeners = currentListeners
//
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
function getState() {
return currentState
}
function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error(' ')
}
//
ensureCanMutateNextListeners()
nextListeners.push(listener)
return function unsubscribe() {
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
function dispatch(action) {
//
if (!isPlainObject(action)) {
throw new Error(' ')
}
//
currentState = currentReducer(currentState, action)
//
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
}
dispatch({ type: ActionTypes.INIT })
return {
dispatch,
getState,
subscribe
}
}
ensureCanMutateNextListeners
の役割は、listeners
が呼び出された間にサブスクリプション(subscribe)が発生したり、サブスクリプション(unsubscribe)が解除されたりした場合、今回の通知では直ちに発効せず、次回中に発効することである.コードには、デフォルト値を得るために
dispatch
メソッドを呼び出し、定義されたタイプの競合を防止するために、reduxがこのように書くことに注意しなければならない.const randomString = () => Math.random().toString(36).substring(7).split('').join('.')
const ActionTypes = {
INIT: `@@redux/INIT${randomString()}`
}
export default ActionTypes
bindActionCreatorsの原理
bindActionCreators
は、dispatch
メソッドを各メソッドに自動的にバインドする役割を上述した.export default function bindActionCreators(actionCreators, dispatch) {
function bindActionCreator(actionCreators, dispatch) {
return function () {
return dispatch(actionCreators.apply(this, arguments))
}
}
if (typeof actionCreators === 'function') {
bindActionCreator(actionCreators, dispatch)
}
const boundActionCreator = {}
for (const key in actionCreators) {
boundActionCreator[key] = bindActionCreator(actionCreators[key], dispatch)
}
return boundActionCreator
}