ReactJS:通过 props 从 parent 改变 child 状态
ReactJS: Mutating child state from parent via props
免责声明:我查看了 Reactjs: how to modify child state or props from parent?,但认为答案不符合我的问题。
所以我有一个可重用的、有状态的对话组件,它根据其状态呈现不同的 DOM。我还必须能够控制从 parent.
渲染哪个 DOM
TL;DR - 我应该如何从 parent 改变 child 组件状态,如果有的话,还有哪些其他选择?
Child:
export default class Conversation extends Component {
constructor(props) {
super(props);
this.state = {
newConversation: props.showNewConversation
};
}
render() {
if (!this.state.newConversation) {
return (
<div>Current Conversation</div>
);
} return (
<div>New Conversation</div>
);
}
}
现在我需要在不同的地方呈现这个组件,但我需要根据 parent 呈现适当的 DOM,即从导航栏你可以创建一个新的对话,并从在用户页面,您可以直接进入与他们的对话,因此我可以通过它的 prop 来控制何时调用 child。
调用 child 并通过属性设置状态:
<Conversation
showNewConversation={this.state.isConversationShown === true}
/>
这目前有效,但有人告诉我这是 React 中的一个非常糟糕的做法,我的问题实际上是为什么这被认为是不好的做法,以及一个好的实践解决方案是什么样的。
在 React 中,一般的最佳做法是尽可能多地制作组件 'state-less'。通常,如果您不加载异步数据或接受用户输入,则不需要状态。
在此示例中,主要问题发生如下:如果 parent 呈现
<Conversation newConversation={true} />
稍后将其重新呈现为
<Conversation newConversation={false} />
然后 child 将不会按预期呈现,因为 React 将 'update' child 对话(re-render)但不会再次调用构造函数。因为你只是在构造函数中将 props 传递给状态,所以 child 永远不会改变。
大多数组件应该只根据其属性呈现。您的 child 可以适应以下内容:
export default class Conversation extends Component {
constructor(props) {
super(props);
}
render() {
if (!this.props.newConversation) {
return (
<div>Current Conversation</div>
);
} return (
<div>New Conversation</div>
);
}
}
在这里,parent 的更新将允许 child 正确地 re-render 因为你直接引用 child 的 render() 函数中的道具.
如果您有更多关于正在呈现的对话的数据,那么您应该将所有数据作为道具传递。即
<Conversation conversationData={{name: 'abc', new: false}} />
然后Conversation组件可以直接在render()方法中访问props
如果你绝对必须改变状态,那么应该是parent:
改变道具的形式
export default class Conversation extends Component {
constructor(props) {
super(props);
this.state = {
newConversation: props.showNewConversation
};
}
// Response to change
componentWillReceiveProps(nextProps){
this.setState({newConversation: this.props.showNewConversation});
}
render() {
if (!this.state.newConversation) {
return (
<div>Current Conversation</div>
);
} return (
<div>New Conversation</div>
);
}
}
免责声明:我查看了 Reactjs: how to modify child state or props from parent?,但认为答案不符合我的问题。
所以我有一个可重用的、有状态的对话组件,它根据其状态呈现不同的 DOM。我还必须能够控制从 parent.
渲染哪个 DOMTL;DR - 我应该如何从 parent 改变 child 组件状态,如果有的话,还有哪些其他选择?
Child:
export default class Conversation extends Component {
constructor(props) {
super(props);
this.state = {
newConversation: props.showNewConversation
};
}
render() {
if (!this.state.newConversation) {
return (
<div>Current Conversation</div>
);
} return (
<div>New Conversation</div>
);
}
}
现在我需要在不同的地方呈现这个组件,但我需要根据 parent 呈现适当的 DOM,即从导航栏你可以创建一个新的对话,并从在用户页面,您可以直接进入与他们的对话,因此我可以通过它的 prop 来控制何时调用 child。
调用 child 并通过属性设置状态:
<Conversation
showNewConversation={this.state.isConversationShown === true}
/>
这目前有效,但有人告诉我这是 React 中的一个非常糟糕的做法,我的问题实际上是为什么这被认为是不好的做法,以及一个好的实践解决方案是什么样的。
在 React 中,一般的最佳做法是尽可能多地制作组件 'state-less'。通常,如果您不加载异步数据或接受用户输入,则不需要状态。
在此示例中,主要问题发生如下:如果 parent 呈现
<Conversation newConversation={true} />
稍后将其重新呈现为
<Conversation newConversation={false} />
然后 child 将不会按预期呈现,因为 React 将 'update' child 对话(re-render)但不会再次调用构造函数。因为你只是在构造函数中将 props 传递给状态,所以 child 永远不会改变。
大多数组件应该只根据其属性呈现。您的 child 可以适应以下内容:
export default class Conversation extends Component {
constructor(props) {
super(props);
}
render() {
if (!this.props.newConversation) {
return (
<div>Current Conversation</div>
);
} return (
<div>New Conversation</div>
);
}
}
在这里,parent 的更新将允许 child 正确地 re-render 因为你直接引用 child 的 render() 函数中的道具.
如果您有更多关于正在呈现的对话的数据,那么您应该将所有数据作为道具传递。即
<Conversation conversationData={{name: 'abc', new: false}} />
然后Conversation组件可以直接在render()方法中访问props
如果你绝对必须改变状态,那么应该是parent:
改变道具的形式export default class Conversation extends Component {
constructor(props) {
super(props);
this.state = {
newConversation: props.showNewConversation
};
}
// Response to change
componentWillReceiveProps(nextProps){
this.setState({newConversation: this.props.showNewConversation});
}
render() {
if (!this.state.newConversation) {
return (
<div>Current Conversation</div>
);
} return (
<div>New Conversation</div>
);
}
}