ReactJS:组件列表的呈现不正确

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReactJS:组件列表的呈现不正确相关的知识,希望对你有一定的参考价值。

我有一个组件(“ComponentA”)在另一个组件(“ComponentB”)的render()内的map()中多次呈现。

此外,我在ComponentB中有一个“ADD”按钮,当它被点击时,在其ComponentB的“state.objects”数组(用于映射ComponentA的实例)中预先挂起(通过'unshift()方法)一个对象。每个前置对象都有一个属性'prop1',我用它设置ComponentA的输入文本值。

问题是我没有在ComponentA的每个实例的状态中得到期望的值:在所有情况下,元素总是具有值'1'(我期望... 3,2,1)。

更重要的是,我看到ComponentA的构造函数只在每个映射循环中调用一次,特别是在最后一个实例的render()调用之前。

这是(简化)代码:

    class ComponentB extends Component {
      constructor(props) {
        super(props) // added upon first reply
        this.handleObjectAdd = this.handleObject.bind(this);
        this.state.objects = [];
      }

      handleObjectAdd() {
        this.state.objects.unshift({prop1: this.state.objects.length + 1});
      }

      render() {
          return (
            <div>
              <button onClick={this.handleObjectAdd}>ADD</button>
              { this.state.objects.map((object, index) =>
                  <ComponentA key={index} details={object}/>
                )
              }
            </div>
          )
        })
      }
    }

    class ComponentA extends Component {
      constructor(props) {
        super(props) // added upon first reply
        console.log('ComponentA constructor called');
        this.state = { details: props.details };
      }
      render() {
        console.log('ComponentA render() called, prop1 value is ' + this.state.details.prop1);
        return (
          <input type="text" value={this.state.details.prop1}></input>
        )
      }
    }

因此,使用上面的代码,单击ADD按钮一次会记录以下内容:

    ComponentA constructor called
    ComponentA render() called, prop1 value is 1

点击第二次按钮记录:

    ComponentA render() called, prop1 value is 1
    ComponentA constructor called'
    ComponentA render() called, prop1 value is 1

点击按钮第3次日志:

    ComponentA render() called, prop1 value is 1
    ComponentA render() called, prop1 value is 1
    ComponentA constructor called'
    ComponentA render() called, prop1 value is 1

... 等等。

在ComponentA的所有实例中,输入文本值为“1”。

我的问题是:

1)如何对其进行编码以获得为ComponentA提供的所需增加值?

2)为什么映射组件的构造函数只调用一次,并且在该特定位置(就在最后一个渲染实例之前)?

注意:上面的代码只是我实际代码的简化版本,仅显示了演示该问题的基本部分。

答案

should never mutate the state directly通过像this.state.objects.unshift()这样的东西 - 使用this.setState()代替。当您直接修改this.state中的数组或对象时,React不知道其中的某些值已更改。这回答了你的问题。因此,而不是直接修改this.state.objects

this.state.objects.unshift({prop1: this.state.objects.length + 1});

您应该以不可变的方式将新项目添加到数组中:

const newItem = { prop1: this.state.objects.length + 1 };
this.setState({
  objects: [newItem].concat(this.state.objects)
});

除此之外,你忘了在super(props)ComponentA的构造者中调用ComponentB。此外,没有必要将传递的道具复制到ComponentA内的组件状态 - 只需使用道具。你可以看到工作代码盒here

另一答案

问题的解决方法来自使用此代码:

    <input value={this.props....} onChange={...} // first version

代替

    <input value={this.state....} onChange={....} // second version

我以前认为第二个版本是正确的,第一个版本阻止输入可编辑。但似乎onChange上的存在使第一个版本工作(正确显示初始值和编辑值并允许编辑)

以上是关于ReactJS:组件列表的呈现不正确的主要内容,如果未能解决你的问题,请参考以下文章

在reactjs中使用基于类的组件时无法呈现数据列表

ReactJs:如何创建一个包装器组件,该组件在单击时会执行某些代码并呈现子组件?

ReactJS 中的路由。显示 URL 但未呈现组件

ReactJS:即使在重新渲染组件后复​​选框状态仍然存在

ReactJS 正确使用有状态和无状态组件的方法?

测试按钮单击 ReactJS 上是不是呈现另一个组件