Javascript 状态更改而不调用setState
因此,我试图在React中构建一个Javascript 状态更改而不调用setState,javascript,reactjs,Javascript,Reactjs,因此,我试图在React中构建一个通知组件。组件的状态包含一个通知数组,这些通知是对象。他们的一把钥匙被“看见”了。正如你可能猜到的,看的目的主要是视觉。每次用户单击通知时,我都会运行一个函数,该函数应该将通知设置为数据库中的通知(用于一致性)和本地状态(用于UI) 数据库部分工作得很好,但由于某些原因,状态更改不起作用。当我放置一些console.logs时,奇怪的是,在调用this.setState之前,我看到'seed'属性变为1。我已经做了好几个小时了,我不知道发生了什么 现在,一些代码
通知组件。组件的状态包含一个通知数组,这些通知是对象。他们的一把钥匙被“看见”了。正如你可能猜到的,看的目的主要是视觉。每次用户单击通知时,我都会运行一个函数,该函数应该将通知设置为数据库中的通知(用于一致性)和本地状态(用于UI)
数据库部分工作得很好,但由于某些原因,状态更改不起作用。当我放置一些console.log
s时,奇怪的是,在调用this.setState
之前,我看到'seed'属性变为1。我已经做了好几个小时了,我不知道发生了什么
现在,一些代码:
import React, {Component} from 'react';
import {connect} from 'react-redux';
import classes from './Notifications.module.css';
import * as actions from '../../../store/actions';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import moment from 'moment';
import {Redirect} from 'react-router-dom';
class Notifications extends Component {
constructor(props) {
super(props);
// Set an interval to update notifications every 4 minutes.
this.update = setInterval(() => {
this.props.fetchNotifications(this.props.username)
}, 240000)
}
state = {
opened: false,
count: 0,
notifications: []
}
componentDidUpdate(prevProps, prevState) {
if (!prevProps.username && this.props.username) this.props.fetchNotifications(this.props.username);
if (!prevProps.notifications && this.props.notifications) {
this.setState({notifications: this.props.notifications, count: this.props.notifications.filter(not => !not.seen).length});
}
if (this.props.notifications) {
if (JSON.stringify(this.state.notifications) !== JSON.stringify(prevState.notifications)) {
this.setState({count: this.state.notifications.filter(not => !not.seen).length})
}
}
}
componentWillUnmount() {
// Clear the update interval
clearInterval(this.update);
}
redirect(model, model_id) {
switch (model) {
case 'sealant_customer':
return <Redirect to={`/profile/sealant-customer/${model_id}`} />;
case 'unapproved_business':
return <Redirect to={`/profile/unapproved-business/${model_id}`} />;
case 'business':
return <Redirect to={`/profile/business/${model_id}`} />;
case 'missed_call':
return <Redirect to={`/data/missed-calls`} />;
default: return null;
}
}
render() {
let content = (
<React.Fragment>
<div className={classes.svgWrapper}>
<p className={classes.counter} style={{opacity: this.state.count === 0 ? '0' : '1'}}>{this.state.count}</p>
<FontAwesomeIcon icon='bell' onClick={() => this.setState(prevState => ({opened: !prevState.opened}))} />
</div>
{this.state.opened && <div className={classes.notificationsWrapper}>
<ul className={classes.notificationsList}>
{this.state.notifications.length !== 0 ? Array.from(this.state.notifications).map(notifi => {
let icon;
switch (notifi.model) {
case 'sealant_customer':
case 'person':
icon = 'user';
break;
case 'business':
case 'unapproved_business':
icon = 'warehouse';
break;
default: icon = 'user';
}
let classArray = [classes.notification];
if (!notifi.seen) classArray.push(classes.unseen);
return (
<li key={notifi.id} className={classArray.join(' ')} onClick={ () => {
// If already seen, simply redirect on click.
if (notifi.seen) return this.redirect(notifi.model, notifi.model_id);
let newNotifications = [...this.state.notifications];
// If not seen, mark as seen in State & in Database.
let index = newNotifications.findIndex(not => notifi.id === not.id);
newNotifications[index].seen = 1;
this.setState({ notifications: newNotifications});
this.props.markSeen(notifi.id, this.props.username);
// Redirect.
return this.redirect(notifi.model, notifi.model_id);
}}>
<div className={classes.iconWrapper}>
<FontAwesomeIcon icon={icon} />
</div>
<div className={classes.textWrapper}>
<p className={classes.msg}>
{notifi.message}
</p>
<label className={classes.ago}>
{moment(notifi.date).fromNow()}
</label>
</div>
</li>
)
}) : <li className={classes.notification} style={{cursor: 'default'}}><p style={{whiteSpace: 'nowrap'}}>No notifications to show...</p></li>}
</ul>
</div>}
</React.Fragment>
)
return (
<div className={classes.wrapper}>
{content}
</div>
)
}
}
const mapStateToProps = state => {
return {
username: state.auth.username,
notifications: state.data.notifications
};
};
const mapDispatchToProps = dispatch => {
return {
fetchNotifications: username => dispatch(actions.fetchNotifications(username)),
markSeen: (id, username) => dispatch(actions.markSeen(id, username))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Notifications);
import React,{Component}来自'React';
从'react redux'导入{connect};
从“./Notifications.module.css”导入类;
将*作为操作从“../../../store/actions”导入;
从'@fortawesome/react fontawesome'导入{FontAwesomeIcon};
从“力矩”中导入力矩;
从'react router dom'导入{Redirect};
类通知扩展组件{
建造师(道具){
超级(道具);
//设置每4分钟更新通知的间隔。
this.update=setInterval(()=>{
this.props.fetchNotifications(this.props.username)
}, 240000)
}
状态={
开:错,
计数:0,
通知:[]
}
componentDidUpdate(prevProps、prevState){
如果(!prevProps.username&&this.props.username)this.props.fetchNotifications(this.props.username);
if(!prevProps.notifications&&this.props.notifications){
this.setState({通知:this.props.notifications,计数:this.props.notifications.filter(not=>!not.seen).length});
}
如果(此.props.notifications){
if(JSON.stringify(this.state.notifications)!==JSON.stringify(prevState.notifications)){
this.setState({count:this.state.notifications.filter(not=>!not.seen.length})
}
}
}
组件将卸载(){
//清除更新间隔
clearInterval(this.update);
}
重定向(模型,模型id){
交换机(型号){
“客户”案例:
返回;
“未经批准的业务”案例:
返回;
“业务”案例:
返回;
“未接来电”案例:
返回;
默认值:返回null;
}
}
render(){
让内容=(
{this.state.count}
this.setState(prevState=>({opened:!prevState.opened}))}/>
{this.state.opened&&
{this.state.notifications.length!==0?数组.from(this.state.notifications).map(notifi=>{
让图标;
交换机(notifi.型号){
“客户”案例:
案例“人”:
图标='用户';
打破
“业务”案例:
“未经批准的业务”案例:
图标=‘仓库’;
打破
默认值:图标='user';
}
让classArray=[classes.notification];
如果(!notifi.seen)classArray.push(classes.unseen);
返回(
- {
//如果已经看到,只需单击重定向即可。
if(notifi.seen)返回此.redirect(notifi.model,notifi.model\u id);
让newNotifications=[…this.state.notifications];
//如果未看到,则标记为在状态和数据库中看到。
让index=newNotifications.findIndex(not=>notifi.id==not.id);
newNotifications[index].seen=1;
this.setState({notifications:newNotifications});
this.props.markSeen(notifi.id,this.props.username);
//重定向。
返回此.redirect(notifi.model,notifi.model\u id);
}}>
{notifi.message}
{时刻(通知日期).fromNow()}
)
}):无需显示的通知…
}
}
)
返回(
{content}
)
}
}
常量mapStateToProps=状态=>{
返回{
用户名:state.auth.username,
通知:state.data.notifications
};
};
const mapDispatchToProps=调度=>{
返回{
fetchNotifications:username=>dispatch(actions.fetchNotifications(username)),
markSeen:(id,用户名)=>dispatch(actions.markSeen(id,用户名))
};
};
导出默认连接(mapStateToProps、mapDispatchToProps)(通知);
如有任何帮助,我们将不胜感激。对于未来的读者-解决方案:
问题是,当我调用行let newNotifications=[…this.state.notifications]代码>我确实创建了一个通知副本,但是一个包含原始通知
对象的副本
有一次,我将行newNotifications[index].seen=1改为newNotifications[index]={…newNotifications[index],seen:1}
一切都像一个符咒一样工作。对于未来的读者,解决方案:
问题是,当我调用行let newNotifications=[…this.state.notifications]代码>我确实创建了一个通知副本,但是一个包含原始通知
对象的副本
有一次我换了李