Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 状态更改而不调用setState_Javascript_Reactjs - Fatal编程技术网

Javascript 状态更改而不调用setState

Javascript 状态更改而不调用setState,javascript,reactjs,Javascript,Reactjs,因此,我试图在React中构建一个通知组件。组件的状态包含一个通知数组,这些通知是对象。他们的一把钥匙被“看见”了。正如你可能猜到的,看的目的主要是视觉。每次用户单击通知时,我都会运行一个函数,该函数应该将通知设置为数据库中的通知(用于一致性)和本地状态(用于UI) 数据库部分工作得很好,但由于某些原因,状态更改不起作用。当我放置一些console.logs时,奇怪的是,在调用this.setState之前,我看到'seed'属性变为1。我已经做了好几个小时了,我不知道发生了什么 现在,一些代码

因此,我试图在React中构建一个
通知
组件。组件的状态包含一个通知数组,这些通知是对象。他们的一把钥匙被“看见”了。正如你可能猜到的,看的目的主要是视觉。每次用户单击通知时,我都会运行一个函数,该函数应该将通知设置为数据库中的通知(用于一致性)和本地状态(用于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]我确实创建了一个通知副本,但是一个包含原始
通知
对象的副本

有一次我换了李