【问题标题】:How to keep state and prevent re-render of react component after changing hierarchy?更改层次结构后如何保持状态并防止重新渲染反应组件?
【发布时间】:2019-10-08 13:50:25
【问题描述】:

我们有:

1) 两个演示组件 - PresentationOnePresentationTwo。并且不可能使用样式来实现它们的效果。

2) 在底层使用状态(类或 useState)的组件 - ComponentWithState。它可以是来自任何库的组件。例如,某种下拉列表。因此,我们不能使用上下文或从外部传递状态。

3) 更改表示类的按钮 - ToggleButton

export const PresentationOne = props => {
  return <div>{props.children}</div>;
};

export const PresentationTwo = props => {
  return <div>{props.children}</div>;
};

export const ComponentWithState = props => {
  const [state, setState] = useState(Math.random());
  return state;
};

export const ToggleButton = props => {
  return <div onClick={props.toggleEffect}></div>;
};

const App = () => {
  const [applyEffect, setApplyEffect] = useState(false);
  const toggleEffect = () => {
    setApplyEffect(!applyEffect);
  };
  return (
    <div className="App">
      {applyEffect ? (
        <PresentationOne>
          <ComponentWithState />
        </PresentationOne>
      ) : (
        <PresentationTwo>
          <ComponentWithState />
        </PresentationTwo>
      )}
      <ToggleButton toggleEffect={toggleEffect} />
    </div>
  );
};

ComponentWithState 将在每次单击按钮后重新渲染为新的状态。是否有可能让这个架构工作?是否有可能告诉 React 它是同一个组件,就像我们可以在列表中使用 key prop 一样?

带有测试套件的 Git 存储库:https://github.com/vitramir/test-react-hierarchy

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    如果您希望子元素成为一个组件的共享引用,您可以尝试在返回标记之前创建该元素:

    const App = () => {
      const [applyEffect, setApplyEffect] = useState(false);
      const toggleEffect = () => {
        setApplyEffect(!applyEffect);
      };
      // This compiles to a React.createElement call
      const childComponent = <ComponentWithState />
      return (
        <div className="App">
          {applyEffect ? (
            <PresentationOne>
              // childComponent is now being passed by reference (I think)
              {childComponent}
            </PresentationOne>
          ) : (
            <PresentationTwo>
              // same as above
              {childComponent}
            </PresentationTwo>
          )}
          <ToggleButton toggleEffect={toggleEffect} />
        </div>
      );
    };
    

    虽然我不确定这是否能满足您的需求

    【讨论】:

    • 它不应该,因为它会返回与结果相同的 DOM。
    • 您的最终目标是什么?更好的性能?共享状态?
    • 如果你只需要保持状态,你可以将它缓存在本地存储中(尽管这会对嵌套对象造成混乱),或者使用 redux 之类的存储,或者使用 reducer 钩子(useReducer)。防止渲染有点不同,一般来说可能是一种反模式,除非你正在解决性能问题
    • 我发现反应问题正是我的意思:github.com/facebook/react/issues/3965
    【解决方案2】:

    经过一天的研究,似乎实现这一目标的唯一方法(通常称为重新父项)是使用 3rd-party 库,例如:

    https://github.com/httptoolkit/react-reverse-portal

    https://github.com/jaredly/react-teleporter

    React repo 中有一个问题:https://github.com/facebook/react/issues/3965

    React Native 没有解决方案。所以,如果您正在阅读这个问题并且您知道解决方案,请将其写在 cmets 中:)

    【讨论】:

      猜你喜欢
      • 2017-03-24
      • 2022-07-08
      • 1970-01-01
      • 2022-01-02
      • 2021-01-27
      • 2023-03-22
      • 2019-04-03
      • 2020-10-07
      • 2021-06-20
      相关资源
      最近更新 更多