免责声明:我看过Reactjs: how to modify child state or props from parent?并且不相信答案符合我的问题。
所以我有一个可重用的有状态会话组件,它根据状态呈现不同的DOM。我还必须能够控制从父级渲染哪些DOM。
TL; DR - 我应该如何改变父组件中的子组件状态,如果有的话,还有其他选项吗?
孩子:
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>
);
}
}
现在我需要在不同的地方渲染这个组件,但我需要根据父级渲染相应的DOM,即从导航栏中创建一个新的对话,然后从用户页面直接进入对话和他们一起,所以当我通过它的道具给孩子打电话时,我可以控制。
通过道具呼叫孩子并设置状态:
<Conversation
showNewConversation={this.state.isConversationShown === true}
/>
这目前正在运作,但我被告知这在React中是一个非常糟糕的做法,我的问题实际上是为什么这被认为是不好的做法,以及什么是良好的实践解决方案。
答案 0 :(得分:4)
在React中,一般的最佳做法是制作尽可能多的组件和无状态&#39;如果可能的话。通常,如果您没有加载异步数据或正在接受用户输入,则状态不是必需的。
在此示例中,主要问题如下:如果父级呈现
<Conversation newConversation={true} />
后来将其重新呈现给
<Conversation newConversation={false} />
然后孩子将无法按预期呈现,因为React将更新&#39;子对话(重新渲染)但不会再次调用构造函数。因为你只将道具转移到构造函数中的状态,所以孩子永远不会改变。
相反,大多数组件只应作为其属性的函数进行渲染。您的孩子可以适应以下情况:
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>
);
}
}
此处,父级的更新将允许子级正确地重新渲染,因为您直接引用子级的render()函数中的props。
如果您有关于正在呈现的对话的更多数据,那么您应该将所有数据作为道具传递。即。
<Conversation conversationData={{name: 'abc', new: false}} />
然后Conversation组件可以直接在render()方法中访问道具。
如果你绝对必须改变状态,那么它应该是父母改变道具的形式:
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>
);
}
}