当使用不同的函数渲染时,ReactJS子组件失去其状态

时间:2017-11-07 01:52:19

标签: reactjs state children

编写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? (还没试过)

注意:我知道我可以为HeaderBody使用变量,因此只需要一个渲染功能。然而,现实世界的案例可能更复杂,可能有多个子组件分布在不同的区域。

即。

        ...

    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定位策略放在HeaderBody组件中是一个很好的解决方案。

是否可以保持ChildComponent的状态?

3 个答案:

答案 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);
}

确保您的子组件具有唯一键,以便它们可以保持状态。