编写ReactJS组件时,我发现子组件暂时失去其状态。事实证明,如果子组件使用不同的渲染函数进行渲染,则会发生这种情况。
即。
父组件有2个子渲染功能,由于条件不同, 它要么在主体中,要么在标题中呈现子组件。
...
renderInHeader = () => (<Header><ChildComponent /></Header>);
renderInBody = () => (<Body><ChildComponent /><Body>);
render = () => {
if (somethingHappens) {
return this.renderInHeader();
}
return this.renderInBody();
}
...
这意味着,当somethingHappens
时,它将使用不同的渲染函数来渲染ChildComponent
。
然后,ChildComponent
将失去其状态。 (子组件的状态被重置)。
我理解为什么会发生这种情况,我实际上有点惊讶于孩子的状态不会更频繁地重置(即每次父母重新渲染该节点时重置)。
但是,处理它的理想解决方案是什么?
避免在子组件中使用状态? (因为它不能保证安全吗?)
向ChildComponent提供key=
,以便在重新渲染期间将其视为独立节点? (不确定key
是否在映射器之外工作)
使用ref
? (不知道它是否有效)
使用新的&#34; Portal&#34;从反应16? (还没试过)
注意:我知道我可以为Header
和Body
使用变量,因此只需要一个渲染功能。然而,现实世界的案例可能更复杂,可能有多个子组件分布在不同的区域。
即。
...
renderInBody = () => (
<Body>
<Header>
<ChildComponent1 />
<ChildComponent2 />
</Header>
<ChildComponent3 />
</Body>
);
renderInHeader = () => (
<Header>
<ChildComponent3 />
<ChildComponent1 />
<Body>
<ChildComponent2 />
</Body>
</Header>
);
render = () => {
if (somethingHappens) {
return this.renderInHeader();
}
return this.renderInBody();
}
...
在这里,子组件1,2,3并没有真正改变,只是他们的位置和父母的结构发生了变化。
而且,我觉得将Child Component定位策略放在Header
和Body
组件中是一个很好的解决方案。
是否可以保持ChildComponent的状态?
答案 0 :(得分:0)
ChildComponent
不应该是if-else
块的一部分,因为它始终会被渲染。
render = () => {
const ParentComponent = somethingHappens ? Header : Body;
return (
<ParentComponent>
<ChildComponent />
</ParentComponent>
);
};
答案 1 :(得分:0)
如果您每次都创建ChildComponent
的新实例,那就更好了。
let alwaysNewChildComp = <ChildComponent />
renderInHeader = () => (<Header>{alwaysNewChildComp}</Header>);
renderInBody = () => (<Body>{alwaysNewChildComp}<Body>);
OR
let alwaysNewChildComp = React.createClass({
render: function () {
return (<div><ChildComponent /></div>)
}
})
renderInHeader = () => (<Header>{alwaysNewChildComp}</Header>);
renderInBody = () => (<Body>{alwaysNewChildComp}<Body>);
它会重置您的ChildComponent
州。
您还可以进一步了解redux
。
答案 2 :(得分:0)
您可以为子组件定义变量,并使用它们在父组件中对渲染进行排序。所以你的示例代码将成为
renderInBody = (child1,child2,child3) => (
<Body>
<Header>
{child1}
{child2}
</Header>
{child3}
</Body>
);
renderInHeader = (child1,child2,child3) => (
<Header>
{child3}
{child1}
<Body>
{child2}
</Body>
</Header>
);
render = () => {
let child1=<ChildComponent key={1}/>;
let child2=<ChildComponent key={2}/>;
let child3=<ChildComponent key={3}/>;
if (somethingHappens) {
return this.renderInHeader(child1,child2,child3);
}
return this.renderInBody(child1,child2,child2);
}
确保您的子组件具有唯一键,以便它们可以保持状态。