当 redux 状态更新时,React componentWillReceiveProps 将接收不触发的道具

React componentWillReceiveProps will receive props not triggering when redux state updates

我有一个存储 actions,这些操作应该在每次添加新的时循环执行。

我有一个组件 MessageListView,它位于一个名为 MessageView 的父级中。当一个新动作添加到我的 socketActions.queue 数组时,componentWillRecieveProps 应该触发,但它没有。

这是我的减速器的样子:

/* Reducer */
const initialState = {
  queue: [{
    type: 'alert',
    action: 'alert',
    completed: false, // Set to true or just delete this object when the action has been completed
    data: {
      message: "the data object dynamically changes based on the type"
    }
  }]
};

export default (state = initialState, action) => {
  switch (action.type) {
  case ADD_ACTION:
    let queue = state.queue
    // action.data['completed'] = false
    queue.push(action.data)
    console.log("Just updated queue", action.data)

    return {
      ...state,
      queue: queue,
      latestAction: new Date()
    }

我的组件是这样连接到商店的:

function mapStateToProps(state){
  console.log(state, "State inside messagelistview.js")
  return {
    actionsQueue: state.socketActions.queue,
    latestAction: state.socketActions.latestAction
  }
};

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({ completeAction }, dispatch);
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(MessageListView);

因此,当我发送新的 ADD_ACTION 操作时,我的状态会更新并 redux-logger 打印出新旧状态,告诉我它们是一样的? ! 。我不知道为什么在我更改 latestAction 值和队列数组后它会这样做。这就是 componentWillRecieveProps 不起作用的原因,但我无法弄清楚为什么状态相同?!

不能 100% 确定这是否能解决任何问题,但我认为您没有正确地将 state.queue 复制到全新的变量队列中。

我建议这样做:

let queue = state.queue.slice()

...看看有什么变化吗?现在您的 queue 变量仍然与 state.queue

相同

您不更改 reducer 中的队列标识。试试这个代码:

case ADD_ACTION:
  let queue = state.queue
  // action.data['completed'] = false
  queue.push(action.data)
  console.log("Just updated queue", action.data)

  return {
    ...state,
    queue: [...queue], // <-- here we copy array to get new identity
    latestAction: new Date()
  }

你应该总是浅拷贝改变的对象。参见 http://redux.js.org/docs/Troubleshooting.html#never-mutate-reducer-arguments

问题是当你这样做时你正在改变你的状态:

let queue = state.queue
// action.data['completed'] = false
queue.push(action.data)

当您直接改变现有状态时,Redux 不会检测到状态差异,也不会通知您的组件商店已更改。

因此,您可以使用以下选项来创建新的 queue 数组:

case ADD_ACTION:
  return {
    ...state,
    queue: state.queue.concat(action.data),
    latestAction: new Date()
  }

或使用 ES6 糖:

case ADD_ACTION:
  return {
    ...state,
    queue: [...state.queue, action.data]
    latestAction: new Date()
  }

连接的组件会浅层检查 (===) 状态是否已更新,并仅在检查失败时才呈现包装组件。在你的情况下,你正在改变你的队列,导致平等检查通过。

如果你像这样改变你的减速器,它将起作用:

state.queue = state.queue.concat(action.data);

或使用 ES6 语法:

state = { ...state, queue: [...state.queue, action.data] };