当 parent 的状态发生变化时,如何更新(re-render)React 中的 child 组件?
How to update (re-render) the child components in React when the parent's state change?
好的,我已经知道一种方法了。但是,我问这个是为了防止我重新发明轮子,因为我是 React 的新手。我的印象是,如果 parent 组件通过道具将她的状态传递给 child 组件,而不是更新 parent 的状态,child 将 re-render 如果需要的话。但事实似乎并非如此。我设置了这个例子,
class Child extends Component {
constructor(props) {
super(props);
this.state = {
number: props.number,
};
}
updateNumber(n) {
this.setState({number: n});
}
render() {
return (<h1>{this.state.number}</h1>);
}
}
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
number: -1,
};
this.child = React.createRef();
setInterval(this.updateState.bind(this), 1000);
}
updateState() {
console.log(this.state);
this.setState({
number: Math.floor((Math.random() * 10) + 1),
});
// this.child.current.updateNumber(this.state.number);
}
render() {
return (
<div>
<Child ref={this.child} number={this.state.number}/>
</div>
);
}
}
在这个例子中,除非我明确定义一个引用并使用它来调用 child 的更新函数(注释部分),否则 child 不会 re-render 每个parent 的状态更新的时间。是这样吗?你是想手动更新你的 children 的状态(呵呵)还是他们应该自动更新(因此 re-render)如果他们的 parent 的状态作为道具传递给他们。
这是因为您的子组件也在使用它自己的状态。总是问自己 state
是否有必要,这是 React 初学者的常见错误。
希望你能通过看这个例子加深理解。我建议您在 componentDidMount
and to clearInterval
in your componentWillUnmount
.
中调用它,而不是在构造函数中调用 setInterval
// Since you are not using state, you can use functional component for your Child component
const Child = ({ number }) => <h1>{number}</h1>;
class Parent extends React.Component {
constructor(props) {
super(props);
this.timer = null;
this.state = { number: 0 };
}
componentDidMount() {
// setInterval after component did mount
this.timer = setInterval(this.incrementNumber, 1000);
}
componentWillUnmount() {
// clearInterval when component is going to unmount
if (this.timer) {
clearInterval(this.timer);
}
}
incrementNumber = () => {
// setState function callback to ensure state received will be latest state
this.setState(prevState => ({ number: prevState.number + 1 }));
}
render() {
const { number } = this.state;
return (
<div>
<Child number={number} />
</div>
);
}
}
你的方法是错误的,不要像这样从子状态更新你的父状态,也不要在子状态中保存道具,它们已经随着父更新而更新。
如果你想更新父表单,子表单传递道具给父表单,如 this.when 父表单更新,子表单也会更新。
class Child extends Component {
constructor(props) {
super(props);
}
updateNumber=()=>{// update parent form child. call this function in somewhere in your component. if you want to pass event pass it as second argument
this.props.updateNumber(newUpdatedNumber,event);
}
render() {
return (<h1>{this.props.number}</h1>);
}
}
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
number: -1,
};
this.child = React.createRef();
setInterval(this.updateState.bind(this), 1000);
}
updateState() {
console.log(this.state);
this.setState({
number: Math.floor((Math.random() * 10) + 1),
});
}
//update parent from child
updateParentFromChild=(updatedNumber,event)=>{//catch function from child
this.setState({
number:updatedNumber
});
}
render() {
return (
<div>
<Child ref={this.child} updateNumber={this.updateParentFromChild} number={this.state.number}/>
</div>
);
}
}
重新渲染子项的一个简单方法是在每次需要重新渲染时更新唯一的关键属性。
<ChildComponent key={this.state.updatedKey}/>
好的,我已经知道一种方法了。但是,我问这个是为了防止我重新发明轮子,因为我是 React 的新手。我的印象是,如果 parent 组件通过道具将她的状态传递给 child 组件,而不是更新 parent 的状态,child 将 re-render 如果需要的话。但事实似乎并非如此。我设置了这个例子,
class Child extends Component {
constructor(props) {
super(props);
this.state = {
number: props.number,
};
}
updateNumber(n) {
this.setState({number: n});
}
render() {
return (<h1>{this.state.number}</h1>);
}
}
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
number: -1,
};
this.child = React.createRef();
setInterval(this.updateState.bind(this), 1000);
}
updateState() {
console.log(this.state);
this.setState({
number: Math.floor((Math.random() * 10) + 1),
});
// this.child.current.updateNumber(this.state.number);
}
render() {
return (
<div>
<Child ref={this.child} number={this.state.number}/>
</div>
);
}
}
在这个例子中,除非我明确定义一个引用并使用它来调用 child 的更新函数(注释部分),否则 child 不会 re-render 每个parent 的状态更新的时间。是这样吗?你是想手动更新你的 children 的状态(呵呵)还是他们应该自动更新(因此 re-render)如果他们的 parent 的状态作为道具传递给他们。
这是因为您的子组件也在使用它自己的状态。总是问自己 state
是否有必要,这是 React 初学者的常见错误。
希望你能通过看这个例子加深理解。我建议您在 componentDidMount
and to clearInterval
in your componentWillUnmount
.
setInterval
// Since you are not using state, you can use functional component for your Child component
const Child = ({ number }) => <h1>{number}</h1>;
class Parent extends React.Component {
constructor(props) {
super(props);
this.timer = null;
this.state = { number: 0 };
}
componentDidMount() {
// setInterval after component did mount
this.timer = setInterval(this.incrementNumber, 1000);
}
componentWillUnmount() {
// clearInterval when component is going to unmount
if (this.timer) {
clearInterval(this.timer);
}
}
incrementNumber = () => {
// setState function callback to ensure state received will be latest state
this.setState(prevState => ({ number: prevState.number + 1 }));
}
render() {
const { number } = this.state;
return (
<div>
<Child number={number} />
</div>
);
}
}
你的方法是错误的,不要像这样从子状态更新你的父状态,也不要在子状态中保存道具,它们已经随着父更新而更新。
如果你想更新父表单,子表单传递道具给父表单,如 this.when 父表单更新,子表单也会更新。
class Child extends Component {
constructor(props) {
super(props);
}
updateNumber=()=>{// update parent form child. call this function in somewhere in your component. if you want to pass event pass it as second argument
this.props.updateNumber(newUpdatedNumber,event);
}
render() {
return (<h1>{this.props.number}</h1>);
}
}
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
number: -1,
};
this.child = React.createRef();
setInterval(this.updateState.bind(this), 1000);
}
updateState() {
console.log(this.state);
this.setState({
number: Math.floor((Math.random() * 10) + 1),
});
}
//update parent from child
updateParentFromChild=(updatedNumber,event)=>{//catch function from child
this.setState({
number:updatedNumber
});
}
render() {
return (
<div>
<Child ref={this.child} updateNumber={this.updateParentFromChild} number={this.state.number}/>
</div>
);
}
}
重新渲染子项的一个简单方法是在每次需要重新渲染时更新唯一的关键属性。
<ChildComponent key={this.state.updatedKey}/>