如何在React中更新上面的父组件n级的状态

时间:2017-04-10 08:28:43

标签: javascript reactjs

检查此处的代码 jsfiddle

我希望从Child组件更新单个项的value属性。但由于道具是不可变的并且不会触发重新渲染,因此代码不起作用。我知道实现这项工作的一种方法是将函数从GrandParent传递给Parent然后传递给Child并使用它来更新GrandpParent的状态。这将触发Child组件中的重新渲染。但这也会导致重新渲染GrandParent,Parent和其他兄弟组件。

// comment

有没有更好的方法来做到这一点,这对我来说似乎不是最佳选择。

2 个答案:

答案 0 :(得分:2)

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick(e) {
    this.props.handleIncrement(e.currentTarget.dataset.key)
  }

  render() {
    return (
      <div>
        <span>{this.props.item.value}</span>
        <button data-key={this.props.item.key} onClick={this.handleClick}>inc</button>
      </div>
    );
  }

}

class Parent extends React.Component {

  render() {
    return (
      <div>
        {
          this.props.list.map((item) => <Child item={item} handleIncrement={this.props.handleIncrement} />)
        }
      </div>
    );
  }

}

class GrandParent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      list: [
        {
          key: 'one',
          value: 1
        },
        {
          key: 'two',
          value: 2
        },
        {
          key: 'three',
          value: 3
        }
      ]
    };

    this.handleIncrement = this.handleIncrement.bind(this)
  }

  handleIncrement(key) {
    this.setState({
        list: this.state.list.map((l) => {
        if (l.key === key) {
            return {key: l.key, value: l.value + 1}
        }
        return l
      })
    })
  }

  render() {
    return (<Parent list={this.state.list} handleIncrement={this.handleIncrement} />);
  }

}

React.render(<GrandParent />, document.getElementById('container'));

您必须从Grand父级传递处理程序,并在需要增加时调用此处理程序。阅读coupling and cohesion了解理论背景。

答案 1 :(得分:1)

React基于单向数据流的概念。这意味着您将数据向下传递给其他组件,这些组件将其作为道具接收并呈现它,或将其传递给另一个子组件。

但是,有时我们希望子组件让父组件发生某些事情。为了解决这个问题,我们使用回调。回调是我们可以作为道具传递给子组件的函数,因此他可以使用它们我们发生了什么。一个典型的例子是将onClick处理程序传递给具有按钮的子组件。然后,当按下按钮时,子组件会像这样调用它:

this.props.onClick()

让父母知道按钮被点击了。这也适用于你的例子。在GrandParent组件中创建一个知道如何递增值的函数。

incrementValue = (idx) => {
    // Copy the list to avoid mutating the state itself.
    let newList = this.state.list.slice();
    newList[idx].value += 1;
    this.setState({list: newList});
}

然后将此函数作为回调传递

<Parent onClick={this.incrementValue}/>

然后将其绑定到按钮单击,如下所示:

<button onClick={this.props.onClick}>inc</button>

阅读this以了解有关React中州和道具的更多信息。