我试图设计一个通知组件,通知将出现在某些场合(如连接问题,成功的修改等)。
我需要通知在几秒钟后消失,所以我触发了一个状态更改,从通知的componentDidMount
中的setTimeout
删除Redux状态的通知。
我可以看到状态确实改变了,但是React-Redux没有重新渲染父组件,所以通知仍然出现在DOM上。
这是我的Redux Reducer:
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.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>
)
}
};
1条答案
按热度按时间chy5wohz1#
你已经把所有东西都正确地连接起来了,但是你错过了Redux的一个关键概念:
使用Redux,你永远不会改变
state
的任何部分。Redux指南:
在reducer中永远不要做的事情:
*修改其参数;
在
deleteSingleNotification
中,使用.splice将旧的通知从数组中删除。相反,您需要返回一个全新的阵列,其中缺少不需要的通知。最简单的方法是使用.filter函数:Here is a JSBin with your working notification system!
这就是为什么它会起作用:React-Redux的工作是在Redux商店的特定部分发生更改时更新组件。它对状态树的每个部分使用
===
测试,以了解是否有任何更改。当你用.splice这样的东西改变状态时,它会检查并认为没有什么不同。
这里有一个例子来演示这个问题:
相反,React-Redux需要我们这样做:
Redux使用这种方法是出于性能原因。它需要很长的时间来遍历一个大的状态树,看看是否一切都是一样的。当你保持你的树不可变时,只需要一个
===
测试,这个过程就变得容易多了。