当我尝试更新其中一个孩子的所有子状态时,我遇到了一些问题,这是我的代码示例。我们的想法是从其中一个组件中自动更新所有组件。
我有新的反应,我只使用了一个星期,所以这可能是一个误解。
https://codesandbox.io/s/430qwoo94
import React from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
filedStr: 'some text',
fieldObj: {
field1: true,
field2: true
}
}
}
updObj = (which, val) => {
this.setState(prevState => ({
fieldObj: {
...prevState.fieldObj,
[which]: val,
},
}));
};
render() {
return (
<div>
<h2>Parent</h2>
Value in Parent Component State: {this.state.fieldObj.field1 ? 1 : 0} : {this.state.fieldObj.field2 ? 1 : 0}
<br />
<Child obj={this.state.fieldObj} onUpdate={this.updObj} />
<br />
<Child obj={this.state.fieldObj} onUpdate={this.updObj} />
<br />
<Child obj={this.state.fieldObj} onUpdate={this.updObj} />
</div>
)
}
}
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
obj: props.obj
}
}
update = (which) => {
this.props.onUpdate(which, !this.state.obj[which]);
this.setState(prevState => ({
obj: {
...prevState.obj,
[which]: !prevState.obj[which],
},
}));
};
render() {
return (
<div>
<h4>Child</h4>
Value in Child State: {this.state.obj.field1 ? 1 : 0} : {this.state.obj.field2 ? 1 : 0}<br />
<button type="button" onClick={(e) => { this.update('field1') }}>field1</button>
<button type="button" onClick={(e) => { this.update('field2') }}>field2</button>
</div>
)
}
}
render(<Parent />, document.getElementById('root'));
答案 0 :(得分:1)
当所有子组件值都可以直接从道具派生时,你不需要在子项中创建一个状态,这是一个道具的副本并维护它,你需要做的是直接修改父状态
import React from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
filedStr: 'some text',
fieldObj: {
field1: true,
field2: true
}
}
}
updObj = (which, val) => {
this.setState(prevState => ({
fieldObj: {
...prevState.fieldObj,
[which]: val,
},
}));
};
render() {
return (
<div>
<h2>Parent</h2>
Value in Parent Component State: {this.state.fieldObj.field1 ? 1 : 0} : {this.state.fieldObj.field2 ? 1 : 0}
<br />
<Child obj={this.state.fieldObj} onUpdate={this.updObj} />
<br />
<Child obj={this.state.fieldObj} onUpdate={this.updObj} />
<br />
<Child obj={this.state.fieldObj} onUpdate={this.updObj} />
</div>
)
}
}
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
obj: props.obj
}
}
update = (which) => {
this.props.onUpdate(which, !this.props.obj[which]);
};
render() {
return (
<div>
<h4>Child</h4>
Value in Child State: {this.props.obj.field1 ? 1 : 0} : {this.props.obj.field2 ? 1 : 0}<br />
<button type="button" onClick={(e) => { this.update('field1') }}>field1</button>
<button type="button" onClick={(e) => { this.update('field2') }}>field2</button>
</div>
)
}
}
render(<Parent />, document.getElementById('root'));
<强> CodeSandbox 强>
但是,如果您想知道为什么您的处理方式不能按预期工作,那是因为您没有根据父级中的状态更新更新子组件的状态,您只需将其设置为一次组件只在组件安装时调用一次,你需要的是实现componentWillReceiveProps
生命周期函数
答案 1 :(得分:0)
在此,我已更新您的代码以满足您的需求 - https://codesandbox.io/s/llnzm2y95z
您对孩子重新渲染的假设是错误的。当子进行重新渲染时,构造函数方法不会被调用,换句话说,构造函数只被调用一次。要使用下一个道具并更改状态,您需要使用渲染和componentWillReceiveProps。请参阅react-component生命周期http://busypeoples.github.io/post/react-component-lifecycle/
问题在于您使用onClick={(e) => { this.update('field1') }}
和onClick={(e) => { this.update('field1') }}
您更新了父级状态,并且此状态再次传递给该子级。但在孩子你没有使用这个新的道具。你&#39;反而使用状态,此状态仅在构造函数中更新,在收到新道具后未更新。 (因为构造函数只被调用一次)
处理新道具的一种方法是直接使用渲染中的道具,因为组件将会重新渲染,并且可以使用更新的道具。
另一种方法是,如果要使用状态,则更新componentWillReceiveProps中的状态。 (我还想指出,强烈建议不要在componentWillReceiveProps和componentDidMount中执行setState)。所以最好先使用第一步。
componentWillReceiveProps(newProps) {
if(newProps !== this.props){
this.setState({newStateObjects})
}
}