更新Redux状态不会触发componentWillReceiveProps方法

25

我正在尝试验证登录信息。确保登录有效后,我想触发一个新路由。 我将state.loginReducer.login作为props传递。当我处理提交事件时,将触发一个操作,改变全局的登录状态。

在这种情况下,ComponentWillReceiveProps不应该被触发吗?因为props已更改。有没有更好的实现这个功能的方法?

handleSubmit (evt) {
    const {
        dispatch,
        login
    } = this.props;

    dispatch(actions.doLogin(value.login));
}

ComponentWillReceiveProps (nextprops) {
    const {
        login
    } = this.nextProps;

    if (login != null) {
        history.pushState({}, '/account');
    }
}

function mapStateToProps (state) {
    return {
        login: state.loginReducer.login
    }
}

export default connect(mapStateToProps)(Login);

显而易见的解决方案是使用回调函数(这就是我现在正在做的),但我仍然不确定在这种情况下是否会触发CWRP。 - João Lima
你是将 mapStateToProps 定义为类方法吗?请确保不要意外地将 undefined 传递给 connect。 - Nathan Hagen
3个回答

33
如果state.loginReducer.login发生改变,那么componentWillReceiveProps方法将被触发。如果你认为你的reducer函数返回一个新的状态值,并且componentWillReceiveProps方法没有被触发,那么请确保新的状态是不可变的。返回与传递给reducer函数相同的状态引用是行不通的。
来自https://github.com/reactjs/redux/blob/master/docs/Troubleshooting.md 这是错误的:
function todos(state = [], action) {
  switch (action.type) {
  case 'ADD_TODO':
    // Wrong! This mutates state
    state.push({
      text: action.text,
      completed: false
    });
  case 'COMPLETE_TODO':
    // Wrong! This mutates state[action.index].
    state[action.index].completed = true;
  }

  return state;
}
这是正确的:
function todos(state = [], action) {
  switch (action.type) {
  case 'ADD_TODO':
    // Return a new array
    return [...state, {
      text: action.text,
      completed: false
    }];
  case 'COMPLETE_TODO':
    // Return a new array
    return [
      ...state.slice(0, action.index),
      // Copy the object before mutating
      Object.assign({}, state[action.index], {
        completed: true
      }),
      ...state.slice(action.index + 1)
    ];
  default:
    return state;
  }
}

3
非常准确。在我的情况下,问题出在我这样写 -- return Object.assign(state, { key: newValue }); -- 而不是这样写 -- return Object.assign({}, state, { key: newValue });。这里的技巧是,用旧对象开始 Object.assign 会更新那个对象,而不是返回一个新的对象,所以 Redux 看起来认为没有改变任何东西,尽管对象的数据已经改变了(因为标识符保持不变)。 - Sasha
1
@Sasha 谢谢,你的评论真的帮了我。我正在创建一个具有相同键的新对象。其中一个键包含一个被改变的数组,但实际上是对先前状态的旧数组的引用。 - rnli
在我的情况下,我肯定是按照你的正确方式进行操作,但CWRP没有被触发。在我的异步更改之前,先前的CWRP显示this.statenextState都处于旧状态,而在更改后,下一个CWRP显示两者都处于新状态。我从未看到旧状态下的this.state和新状态下的nextState - hippietrail
请看一下这个问题,如果您能帮忙我会非常感激:- https://stackoverflow.com/questions/49152672/render-function-not-getting-call-after-dispatching-action-from-component - user2028

12
ComponentWillReceiveProps (nextprops)

应该是

componentWillReceiveProps (nextprops)

应该使用小写字母C。实际上,mapStateToProps 会触发 componentWillReceiveProps。我对此非常确定。


3

请按照以下步骤操作:

function mapStateToProps (state) {
    return {
        login: Object.assign({}, state.loginReducer.login),
    }
}

为确保返回的对象实际上是 new


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接