Reactjs 我的Redux状态已经改变,为什么';不反应触发重新渲染?

Reactjs 我的Redux状态已经改变,为什么';不反应触发重新渲染?,reactjs,redux,react-redux,Reactjs,Redux,React Redux,我试图设计一个通知组件,在某些情况下(如连接问题、成功修改等)会出现通知 我需要通知在几秒钟后消失,因此我正在触发一个状态更改,从通知的组件didmount中的setTimeout从Redux状态删除通知 我可以看到状态确实发生了变化,但是React-Redux没有重新呈现父组件,因此通知仍然显示在DOM上 这是我的Redux减速机: const initialState = { notifications: [] } export default function (state =

我试图设计一个通知组件,在某些情况下(如连接问题、成功修改等)会出现通知

我需要通知在几秒钟后消失,因此我正在触发一个状态更改,从通知的
组件didmount
中的
setTimeout
从Redux状态删除通知

我可以看到状态确实发生了变化,但是React-Redux没有重新呈现父组件,因此通知仍然显示在DOM上

这是我的Redux减速机:

const initialState = {
    notifications: []
}

export default function (state = initialState, action) {
  switch(action.type) {
    case CLEAR_SINGLE_NOTIFICATION:
      return Object.assign ({}, state, {
        notifications: deleteSingleNotification(state.notifications, action.payload)
      })
      case CLEAR_ALL_NOTIFICATIONS:
        return Object.assign ({}, state, {
          notifications: []
        })
      default:
        return state
    }
}

function deleteSingleNotification (notifications, notificationId) {
  notifications.some (function (notification, index) {
    return (notifications [index] ['id'] === notificationId) ?
           !!(notifications.splice(index, 1)) :
           false;
  })

  return notifications;
}
和我的反应组件(
Main
Notification
):

const initialState = {
    notifications: []
}

export default function (state = initialState, action) {
  switch(action.type) {
    case CLEAR_SINGLE_NOTIFICATION:
      return Object.assign ({}, state, {
        notifications: deleteSingleNotification(state.notifications, action.payload)
      })
      case CLEAR_ALL_NOTIFICATIONS:
        return Object.assign ({}, state, {
          notifications: []
        })
      default:
        return state
    }
}

function deleteSingleNotification (notifications, notificationId) {
  notifications.some (function (notification, index) {
    return (notifications [index] ['id'] === notificationId) ?
           !!(notifications.splice(index, 1)) :
           false;
  })

  return notifications;
}
/*MAIN.JS*/
类主扩展组件{
renderDeletedVideoNotifications(){
log(“呈现通知”);
const clearNotification=this.props.clearNotification;
返回此.props.notifications.map((通知)=>{
返回
});
}
render(){
console.log(“重新招标”);
返回(
{this.props.children}
{this.renderDeletedVideoNotifications()}
);
}
}
函数MapStateTops(状态){
返回{logStatus:state.logStatus,通知:state.notifications.notifications};
}
功能图DispatchToprops(调度){
返回bindActionCreators({checkLogStatus,logOut,clearNotification,clearAllNotifications},dispatch);
}
导出默认连接(mapStateToProps、mapDispatchToProps)(主);
/*NOTIFICATION.JS*/
导出默认类通知扩展组件{
建造师(道具){
超级(道具);
this.state={show:true}
}
组件将接收道具(下一步){
如果(nextrops.message){
this.setState({show:true});
}
}
clearNotification(notificationId){
this.props.clearNotifications(notificationId);
}
componentDidMount(){
log('notification mount');
设置超时(()=>{
console.log(“超时”);
this.props.clearNotification(this.props.notificationId);
}, 1000);
}
关闭通知(){
this.props.clearNotification(this.props.notificationId);
this.setState({show:false});
}
render(){
构造通知样式=()=>{
if(this.props.style==“error”){
返回{backgroundColor:'rgba(152,5,19,0.8)}
}
返回{backgroundColor:'rgba(81301010.8)}
};
如果(!this.state.show){
返回null;
}
返回(
关闭
{this.props.message}
)
}
};

您已将所有内容正确连接,但缺少Redux的一个关键概念:

使用Redux,您永远不会改变
状态的任何部分。
从:

在减速器内不应执行的操作:

  • 改变其论点
  • 执行API调用和路由转换等副作用
  • 调用非纯函数,例如Date.now()或Math.random()
deleteSingleNotification
中,您正在使用.splice从阵列中删除旧通知。相反,您需要返回一个全新的数组,其中缺少不需要的通知。最简单的方法是使用.filter函数:

function deleteSingleNotification(notifications, notificationId){
    return notifications.filter (notification => {
        return notification.id !== notificationId
    }
}

这就是为什么这样做的原因:React Redux的工作是在Redux存储的特定部分发生更改时更新组件。它对状态树的每个部分都使用
==
测试,以了解是否有任何变化

当您使用.splice之类的东西更改状态时,它会检查并认为没有什么不同

下面是一个示例来说明问题:

var array = [ 'a', 'b', 'c' ]

var oldArray = array

array.splice (1, 1) // cut out 'b'

oldArray === array // => true!  Both arrays were changed by using .splice,
                   // so React-Redux *doesn't* update anything
相反,React Redux需要我们这样做:

var array = [ 'a', 'b', 'c' ]

var oldArray = array

array = array.filter (item, index => index !== 1) // new array without 'b'

oldArray === array // false.  That part of your state has changed, so your
                   // componenet is re-rendered

出于性能原因,Redux使用这种方法。在一棵大的状态树中循环,看看是否一切都是一样的,这需要很长的时间。当你保持你的树不可变时,只需要一个
=
测试,这个过程就会变得容易得多。

如果组件接收到新的属性,它应该重新呈现自己。尝试在主组件的
render
方法中记录
this.props.notifications
,查看通知是否正在实际更改。谢谢,这就是问题所在!我意识到避免突变的必要性,但我认为我实现它的方式是一种不变的方式。使用Object.assign不会将新项返回到状态?对我来说,我不在乎过去状态上的拼接,因为函数只是返回一个新状态,尽管发生了变化,但它将使用Object.assign方法返回一个新状态。我遗漏了什么吗?@Nicolas Object.assign()只做一个浅拷贝。所以状态会被复制,但通知数组会发生变异。我也遇到过类似的情况。我使用这个let newState=state;newState.value=newValue;在我的例子中,副本是通过引用的,因此我实际上是在修改父语句。为了进行深度复制,我做了以下操作并最终解决了我的问题-让newState={…state};