检查此处的代码 jsfiddle
我希望从Child组件更新单个项的value属性。但由于道具是不可变的并且不会触发重新渲染,因此代码不起作用。我知道实现这项工作的一种方法是将函数从GrandParent传递给Parent然后传递给Child并使用它来更新GrandpParent的状态。这将触发Child组件中的重新渲染。但这也会导致重新渲染GrandParent,Parent和其他兄弟组件。
// comment
有没有更好的方法来做到这一点,这对我来说似乎不是最佳选择。
答案 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中州和道具的更多信息。