【问题标题】:Child componenet not updating when parent component is updating its array in react当父组件在反应中更新其数组时,子组件未更新
【发布时间】:2017-04-17 16:15:09
【问题描述】:

我在父反应组件中有一个项目列表,我在其中添加了新项目和更新项目。子组件将接收道具中的项目并渲染它。

当父状态正在更新时,子组件不会更新其值。 我是否需要在“componentWillReceiveProps”中更新子组件状态?正确的做法是什么。

Code Example 
// parent component 
import React, { Component } from "react";
import TestList from '../controls/testlistview'

export default class TestView extends Component {
    constructor(props) {
        super();
        this.state = {
            items: []
        };
    }

    render() {
        return (<div>
            <button onClick={this.addItem.bind(this)}> Add item</button>
            <button onClick={this.changeFirstItemText.bind(this)}> Change item</button>
            <TestList items={this.state.items} index={index}/>
        </div>);
    }

    addItem() {
        var items = this.state.items.map(s=> s);

        items.push('new one');
        this.setState({
            items: items
        });
    }



    changeFirstItemText() {
        var items = this.state.items.map(s=> s);
        items[0] = "changed text";
        this.setState({
            items: items
        });
    }
}



//Child component
import React, { Component } from "react";

export default class TestList extends Component {
    constructor(props) {
        super();
        debugger;
        this.state = {
            rootNodes: props.items
        };
    }

    componentWillReceiveProps(nextProps){
        debugger;
    }

    render() {
        var items = this.state.rootNodes.map((s) => {
            return <div>{s}</div>;
        });
        return <div>{items}</div>;
    }
}

【问题讨论】:

  • 为什么你的孩子会有自己的状态?

标签: reactjs ecmascript-6


【解决方案1】:

代替

render() {
        var items = this.state.rootNodes.map((s) => {
            return <div>{s}</div>;
        });
        return <div>{items}</div>;
    }

你从道具中获得物品

render() {
        var items = this.props.items.map((s) => {
            return <div>{s}</div>;
        });
        return <div>{items}</div>;
    }

您不必再次将 props 分配给 TestList 状态,否则您需要再次从 TestList 执行 setState() 才能再次触发渲染。 (这不是必要的步骤)

http://codepen.io/kossel/pen/ObQLoR

【讨论】:

    【解决方案2】:

    在 TestList 类中,您不应该将 props 分配给组件的状态 - 这是在 React 中引起重大问题的可靠方法,也是您出现问题的原因。请参阅 my answer here 了解为什么这是一个坏主意。

    如果您将您的 TestItem 更改为以下内容,那么它应该可以正常工作。

    export default class TestList extends Component {
        constructor(props) {
            super();
            debugger;
        }
    
        componentWillReceiveProps(nextProps){
            debugger;
        }
    
        render() {
            var items = this.props.items.map((s) => {
                return <div>{s}</div>;
            });
            return <div>{items}</div>;
        }
    }
    

    【讨论】:

      【解决方案3】:

      原因是您正在通过子组件的状态创建 ui 元素。 有两种方法可以解决这个问题:
      1. 像这样更新componentWillReceiveProps()函数中的状态值

       componentWillReceiveProps(newProps){
              this.setState({
                  rootNodes: newProps.items
              });
      }
      

      2.像这样直接从props值创建ui元素-

      render() {
          var uiItems = this.props.items.map((item) => {
              return <div>{item}</div>;
          });
          return (<div>{uiItems}</div>);
      }
      

      【讨论】:

      • 谢谢。我需要操作道具和创建状态项,所以第一个选项有效,但我的问题是,这是正确的做法吗?
      • 两种方式都是正确的,当你想存储组件的一些信息时使用状态变量,在这种情况下你正在创建固定的 ui 元素,所以更好的方式是第二种方式,让我们假设您正在创建一些文本字段或用户可以更改的任何其他用户界面,那么在这种情况下,第一个选项会更好。
      • 在我的实际应用中,它不仅仅是固定的 UI,这就是使用状态的原因。谢谢你的回答。
      • 我强烈建议不要使用选项 1,原因在我的回答中列出。 React 就是要有一个单一的事实来源,而使用 props 来生成状态正好适合这一点。
      • 要备份我上面的评论,请参阅SO React docs
      猜你喜欢
      • 2018-04-22
      • 2019-12-04
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 2017-05-05
      • 1970-01-01
      • 2019-02-17
      • 1970-01-01
      相关资源
      最近更新 更多