我正在尝试设计一个通知组件,在某些情况下通知会出现(例如连接问题,成功的修改等)。
我需要几秒钟后通知才能消失,因此我正在触发状态更改,以从通知setTimeout内部的Redux状态删除通知componentDidMount。
setTimeout
componentDidMount
我可以看到状态确实发生了变化,但是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; }
和我的React组件(Main和Notification):
Main
Notification
/* 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的一个关键概念:
state
从Redux指南:
在减速器中永远不应该做的事情: 改变其论点; 执行副作用,例如API调用和路由转换; 调用非纯函数,例如Date.now()或Math.random()。
在减速器中永远不应该做的事情:
在中deleteSingleNotification,您正在使用.splice将旧的通知从数组中删除。相反,您需要返回一个全新的数组,其中缺少不需要的通知。最简单的方法是使用.filter函数:
deleteSingleNotification
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使用此方法。遍历一棵大状态树以查看是否所有内容都花了很长时间。当您将树保持 不变时 ,只需进行===测试即可,过程变得更加容易。