【问题标题】:what is the best way to create a state of array or state of array of objects创建数组状态或对象数组状态的最佳方法是什么
【发布时间】:2021-09-09 21:26:38
【问题描述】:

我在客户端和服务器之间建立了 websocket 连接。

客户端想要显示 ID 列表及其 progressValue。

另一端的服务器总是发送例如长度为 1 的 obj 数组

[{"processid": "1","progressVal" : 10%}]
[{"processid": "2","progressVal" : 5%}]
[{"processid": "1","progressVal" : 25%}]
[{"processid": "3","progressVal" : 1%}]
[{"processid": "2","progressVal" : 12%}]
like that it keeps sending processid and its progressVal

现在在服务器端它没有任何状态。它只是将数据发送到客户端。

在客户端,客户端想要监听服务器发送的消息,并创建一个数组来存储progressid和progressVal,以便它可以循环显示它在GUI中。

逻辑:

  1. 想要创建一个包含 processid 和 progressVal 列表的单个数组
  2. 检查创建的列表中是否已经存在processid, 如果是,则检查progressVal 是否相同,如果不是,则更新progressVal 如果否,则将 processid 和 progressVal 添加到此数组中。

预期结果

  dataFromServer = [{"processid": "1","progressVal" : 10%}]
  then proList = [{"processid": "1","progressVal" : 10%}]
  dataFromServer = [{"processid": "2","progressVal" : 5%}]
  then proList = [{"processid": "1","progressVal" : 10%},{"processid": "2","progressVal" : 5%} ]
  dataFromServer = [{"processid": "1","progressVal" : 25%}]
  then proList = [{"processid": "1","progressVal" : 25%},{"processid": "2","progressVal" : 5%} ]
  dataFromServer = [{"processid": "3","progressVal" : 1%}]
  then proList = [{"processid": "1","progressVal" : 25%},{"processid": "2","progressVal" : 5%}, {"processid": "3","progressVal" : 1%} ]
  dataFromServer = [{"processid": "2","progressVal" : 12%}]
  then proList = [{"processid": "1","progressVal" : 25%},{"processid": "2","progressVal" : 12%}, {"processid": "3","progressVal" : 1%} ]
class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      dataFromServer : ""
    }
  }
 componentDidMount(){
     client.onmessage = (message) => {
      this.setState({dataFromServer: JSON.parse(message.data)});
    };
  }
  render() {
    if(!this.state.dataFromServer){
      return "loading"
    }
    else if(this.state.dataFromServer && this.state.dataFromServer.length >0){
      return(
        <div>
        <processList dataFromServer={this.state.dataFromServer}/>
      </div>
      );
    }
  }
}
export default App;
class processList extends Component {
  constructor(props){
    super(props);
    this.state = {  
      proList : [{
      id: "",
      progVal: parseInt("0%")
}]   // i want to set here initial values for id and progVal
    }
  }
  componentDidMount(){
    if(this.props.dataFromServer){
      this.props.dataFromServer.map(d => {
        let arr = [];
        let objToPush = {id: element.id, progVal: element.progVal};
        arr.push(objToPush);
        this.setState ({
          proList: arr
        });
      });
    }
  }
  componentDidUpdate(prevProps, prevState){     //want to push into array if processId is new, and want to update the progVal if processId already exists in array
    this.props.dataFromServer.map(d => {

      }
      else if(prevState.proList.id == d.id){
                                                    //not sure how to do logic here.
      } 
    })
  }
    render(){
    return(
      this.state.proList.map(data => {              
          return(
            <div>
                <p>{data.id}</p>
                <p>{data.progVal}</p>
            </div>
            );
      })
    );
};
  }

【问题讨论】:

    标签: javascript arrays reactjs setstate


    【解决方案1】:

    如果您想设置更新 proList(即对象数组,这是我为此建议的方法),这里是代码。

    1. 您将映射新收到的数据
    2. 通过proList 数组状态变量,您将查看是否有任何元素与所考虑的元素具有相同的id (d)
    3. 如果通过第 2 步找到一个元素,它的索引将大于 -1(find() 方法返回 -1 如果没有找到匹配项,或者如果找到的元素给出了正确的索引),请检查 @ 是否新接收到的数据对象(d)的 987654326@ 与旧数据对象相同。如果没有,请更新它。
    4. 如果通过第 2 步没有找到元素,请将 newfound 对象推送到数组中,然后将proList 设置到数组中并进行更新。

    .

      componentDidUpdate(prevProps, prevState) {
        let arr = [...this.state.proList]; // side-note: do this, because you don't want to mutate the original array like you were doing in your code
    
        this.props.dataFromServer.forEach((d) => {
          let index = prevState.proList.findIndex((el) => el.id === d.id); // where is uid coming from? all the other places you've written 'id' and not 'uid'
    
          let objectToPush = { id: d.id, progVal: d.progVal };
          if (index > -1) {
            // i.e, if some occurence is found,
            if (arr[index].progVal !== d.progVal) {
              arr[index] = objectToPush; // insert this object at the index of the old object
              this.setState({
                proList: arr
              });
            }
          } else {
            arr.push(objectToPush); // append to the array, since it's a new id
            this.setState({
              proList: arr
            });
          }
        });
      }
    

    【讨论】:

    • 肯定会试一试。但是在 componentdidmount 中呢 -> 你认为将数据推送到数组状态的方法是错误的吗?
    • 对不起,它的“id”不是“uid”
    • 是的,因为这将改变数组状态(因为push( ) 改变了原始数组),并且它不会触发重新渲染(不是您希望它重新渲染,但无论如何)。在 react-osphere 中,这被认为是一种不好的做法。 Official documentation advises to consider states as immutable。在状态变量类似于数组或对象的情况下,最好复制一个,对其进行操作,然后更新状态变量。
    • 所以我有一个问题:根据您的代码,您建议使用 proList 而不是 dataList 正确。但是如何在 proList 中设置初始值。例如,我希望 id 和 progVal 的初始值为空。我还更新了 componentdidmount 的代码。
    • 我尝试使用该代码,但出现此错误:错误:超出最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时会发生这种情况
    猜你喜欢
    • 2014-12-17
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 2015-04-28
    • 2015-07-02
    • 1970-01-01
    相关资源
    最近更新 更多