我的Redux状态已更改,为什么React无法触发重新渲染?

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

我需要几秒钟后通知才能消失,因此我正在触发状态更改,以从通知setTimeout内部的Redux状态删除通知componentDidMount

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

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 */

class Main extends Component {

renderDeletedVideoNotifications() {

console.log('rendering notifications');

const clearNotification = this.props.clearNotification;

return this.props.notifications.map((notification)=> {

return <Notification

key={notification.id}

message={notification.message}

style={notification.style}

clearNotification={clearNotification}

notificationId={notification.id}

/>

});

}

render() {

console.log('rerendering');

return (

<div className="_main">

<Navbar location={this.props.location} logStatus={this.props.logStatus}

logOut={this.logout.bind(this)}/>

<div className="_separator"></div>

{this.props.children}

<BottomStack>

{this.renderDeletedVideoNotifications()}

</BottomStack>

</div>

);

}

}

function mapStateToProps(state) {

return {logStatus: state.logStatus, notifications: state.notifications.notifications};

}

function mapDispatchToProps(dispatch) {

return bindActionCreators({checkLogStatus, logOut, clearNotification, clearAllNotifications}, dispatch);

}

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

/* NOTIFICATION.JS */

export default class Notification extends Component{

constructor(props){

super(props);

this.state = {show: true}

}

componentWillReceiveProps(nextProps){

if(nextProps.message){

this.setState({show: true});

}

}

clearNotification(notificationId){

this.props.clearNotifications(notificationId);

}

componentDidMount(){

console.log('notification mount');

setTimeout(()=>{

console.log('timed out');

this.props.clearNotification(this.props.notificationId);

}, 1000);

}

closeNotification(){

this.props.clearNotification(this.props.notificationId);

this.setState({show: false});

}

render(){

const notificationStyles = () =>{

if (this.props.style === "error"){

return {backgroundColor: 'rgba(152, 5, 19, 0.8)'}

}

return {backgroundColor: 'rgba(8, 130, 101, 0.8)'}

};

if(!this.state.show){

return null;

}

return (

<div className="notification" style={notificationStyles()}>

<div className="notificationCloseButton" onClick={this.closeNotification.bind(this)}>

<i className="material-icons">close</i>

</div>

{this.props.message}

</div>

)

}

};

回答:

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

使用Redux,您 永远不会 突变的任何部分state

从Redux指南:

在减速器中永远不应该做的事情:

  • 执行副作用,例如API调用和路由转换;
  • 调用非纯函数,例如Date.now()或Math.random()。

在中deleteSingleNotification,您正在使用.splice将旧的通知从数组中删除。相反,您需要返回一个全新的数组,其中缺少不需要的通知。最简单的方法是使用.filter函数:

function deleteSingleNotification(notifications, notificationId){

return notifications.filter (notification => {

return notification.id !== notificationId

}

}

这是您的工作通知系统的JSBin!


因此,这就是这样做的原因: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使用此方法。遍历一棵大状态树以查看是否所有内容都花了很长时间。当您将树保持

,只需进行===测试即可,过程变得更加容易。

以上是 我的Redux状态已更改,为什么React无法触发重新渲染? 的全部内容, 来源链接: utcz.com/qa/410779.html

回到顶部