在 React 中更新数组

IT技术 javascript reactjs firebase
2021-04-10 07:29:59

我来自 Angular 1.x,并希望使用 React / Redux 更新无序列表。

在 console.log 中,我看到数组正在更新,但它似乎没有绑定到 DOM。我有以下——

onKeyPress 输入,我有一个函数可以推送到消息数组。

<ul className="list-inline">
  {messages.map(function(message, key){
    return (
      <li key={key} message={message}>{message}</li>
    );
  })}
</ul>

更新 我有以下(但还没有运气)一些笔记。我正在使用 Firebase 侦听事件并添加到数组中。想知道它是否是绑定问题?——

class Comments extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = {messages: this.props.messages};
  }

  componentDidMount() {
    const path = '/comments/all';
    // Firebase watches for new comments
    firebase
      .database()
      .ref(path)
      .on('child_added', (dataSnapshot) => {
          this.state.messages.push(dataSnapshot.val());
          this.setState({
            messages: this.state.messages
          });
          //console.log(dataSnapshot.val());
      });
  }

  render() {
    const messages = this.state.messages;
    return (
      <ul className="list-inline">
        {messages.map(function(message, key){
          <li key={key}>{message}</li>
        })}
      </ul>
    );
  }
}
3个回答

您需要在组件中设置消息state

getInitialState() {
  return {
    messages: []
  }
}

然后在您的函数中,设置状态:

this.setState({messages: updatedMessages})

然后映射消息状态或messages变量render

const messages = this.state.messages;


<ul className="list-inline">
  {messages.map(function(message, key){
etc...
setState调用对于 OP 的场景来说是不安全的,因为它们正在根据现有状态更新状态(添加到状态的messages数组中)。当基于现有状态更新状态时,必须使用 的回调形式,setState因为状态更新是异步的并且可以合并。详情:facebook.github.io/react/docs/...
2021-06-03 07:29:59

放置消息数组并设置状态更改以呈现 DOM。你应该阅读https://facebook.github.io/react/docs/component-specs.html

两个问题:

  1. 你不会直接改变 React 中的状态对象。相反,提供一个包含新条目数组setState
  2. 当基于现有状态更新状态时,必须使用 的函数回调版本setState,而不是接受对象的版本,因为状态更新是异步的并且可能会被合并。使用对象版本通常会起作用,但不能保证;事实上,在某些时候保证不会

React 文档中的更多信息:正确使用状态(“不要直接修改状态”和“状态更新可能是异步的”部分)。

让我们看看更新数组的各种方法:

添加到最后(附加):

this.setState(({messages}) => ({
    messages: [...messages, newValue]
}));

在您的情况下,newValue将是dataSnapshot.val().

(我们需要()围绕对象初始值设定项,否则它{似乎会启动一个完整的函数体而不是一个简洁的表达式体。)

添加到开头(前置):

大体相同,我们只是在不同的地方插入新元素:

this.setState(({messages}) => ({
    messages: [newValue, ...messages]
}));

(我们需要()围绕对象初始值设定项,否则它{似乎会启动一个完整的函数体而不是一个简洁的表达式体。)

更新数组中的现有项目

假设您有一个对象数组,并且想要更新变量中的一个对象targetElement

this.setState(({messages}) => {
    messages = messages.map(element => {
        return element === targetElement
            ? {...element, newValue: "new value"}
            : element;
    });
    return {messages};
}));

删除数组中的现有项目

假设您有一组带有id的对象,并且想要删除其中的一个targetId

this.setState(({messages}) => {
    messages = messages.filter(element => element.id !== targetId);
    return {messages};
}));

按索引

警告:在 React 中按索引更新数组通常不是最佳实践,因为状态更新是一起批处理的,索引可能会过时。相反,根据识别属性或类似属性工作。

但是,如果您必须使用索引并且您知道它不会过时:

this.setState(({messages}) => {
    messages = messages.filter((e, index) => index !== targetindex);
    return {messages};
}));