redux的reducer中state为什么每次得浅拷贝一下

1.使用

在redux开发中我们经常会在写reducer的时候进行浅拷贝, 脚本如下

export default function mainInfo (state = initialState, action) {
  let newState = Object.assign({}, state);
  ...
}

目的也只是为了"骗"redux进行刷新,作者也会考虑的该库的效率,不会进行深层的对比.

2.原理

对于以上问题,我们也可以查看下为什么一定要进行浅拷贝.

2.1 redux源码

进入redux源码中combineReducers.js文件的最后,我们可以看到

  ...
    const nextState = {}
    for (let i = 0; i < finalReducerKeys.length; i++) {
      const key = finalReducerKeys[i]
      const reducer = finalReducers[key]
      const previousStateForKey = state[key]
      const nextStateForKey = reducer(previousStateForKey, action)
      if (typeof nextStateForKey === 'undefined') {
        const errorMessage = getUndefinedStateErrorMessage(key, action)
        throw new Error(errorMessage)
      }
      nextState[key] = nextStateForKey
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    return hasChanged ? nextState : state

其中finalReducerKeys就是我们经常使用的方法合成reducer的combineReducers中参数, 如:

import { combineReducers } from 'redux';
import userinfo from './userinfo';
import main from './main.js';
export default combineReducers({
    userinfo, main
});

不知道你注意了没有, hasChanged决定了最后返回的是nextState还是state,前者是新的对象,后者是原来的对象.

2.2 react-redux源码

进入Provider.js文件中,我们可以看到subscribe方法如下:

  subscribe() {
    const { store } = this.props

    this.unsubscribe = store.subscribe(() => {
      const newStoreState = store.getState()

      if (!this._isMounted) {
        return
      }

      this.setState(providerState => {
        // If the value is the same, skip the unnecessary state update.
        if (providerState.storeState === newStoreState) {
          return null
        }

        return { storeState: newStoreState }
      })
    })

    // Actions might have been dispatched between render and mount - handle those
    const postMountStoreState = store.getState()
    if (postMountStoreState !== this.state.storeState) {
      this.setState({ storeState: postMountStoreState })
    }
  }

看他的订阅方法,其中newStoreState就是我们在2.1中看到返回的state.最后他会通过setState来进行重新渲染.它这里就是使用了之前记录的的storeState和现在获取到的newStoreState进行全等判断. 看到了吧,如果2.1中返回新state和旧state的区别了吧.

3.结论

如果想"骗"reducer刷新,就得在reducer中浅拷贝.

4.其他

如果使用了reducer的浅拷贝还是没有刷新页面,那么可能有如下原因.
1.在react层面,组件使用了PureComponent,connect包裹后.mapStateToProps返回的对象,每一个key对应的值没有被浅拷贝(或者是指针没有改变,导致全等判断结果)
2.是否在shouldComponentUpdate中写了相关逻辑
3.其他地方是否报错

你可能感兴趣的:(redux的reducer中state为什么每次得浅拷贝一下)