【问题标题】:In which order are React components re-rendered when global state is updated through hooks?当通过钩子更新全局状态时,React 组件按什么顺序重新渲染?
【发布时间】:2021-08-21 12:03:27
【问题描述】:

给定一个顶级 App 组件,它呈现以下层次结构:

<Parent>
  <Child />
</Parent>

如果ParentChild 都调用同一个钩子来获取某个全局状态,并且该状态发生了变化,那么ParentChild 会先重新渲染吗?

另外,假设它们都使用来自全局状态的某个变量 user,并且 Parent 仅在 user 未定义时才呈现其 children 属性。 Child 道具是否会被 undefined user 渲染?

【问题讨论】:

  • 例如,如果您仅在用户在场时渲染孩子,我推断您的意思是这样的 - { user && ChildComponent 将不会被挂载。所以我认为它不可能使用undefined 进行渲染
  • 可以通过在渲染函数中添加console.log来检查。
  • @Shyam 有点像。我的意思是在Parent 我会有{user &amp;&amp; children}。在这种情况下,children 又将是 &lt;Child /&gt;。如果userundefined,我预计Child 甚至不应该被渲染,但在我的实际生产应用程序中它是,所以我在Child 中收到user undefined 错误。请注意,ParentChild 都从全局挂钩中获取 user - 它不是从 Parent 传递到 Child
  • @DennisVash 我已经尝试过了,我在本地和生产中得到了不同的日志。在本地,Parent 首先渲染,但在生产中,Child 首先渲染,即使考虑到我在Parent 中的条件,我希望它根本不会渲染。本地控制台日志:AuthLayout CustomerDetailsForm UPDATING USER VARIABLE USER VARIABLE UPDATED AuthLayout 生产控制台日志:AuthLayout CustomerDetailsForm UPDATING USER VARIABLE USER VARIABLE UPDATED CustomerDetailsForm TypeError: user is undefined in CustomerDetailsForm

标签: reactjs react-hooks


【解决方案1】:

这是一个 sn-p 记录父母和孩子的装载/卸载。仅当状态值为奇数时才呈现子级。两个组件都在访问同一个上下文。

const { useState, createContext, useContext, useEffect, useRef } = React;

const ViewContext = createContext();
const ActionsContext = createContext();

function MyContainer() {
  const [contextState, setContextState] = useState(0);

  return (
    <ViewContext.Provider value={contextState}>
      <ActionsContext.Provider value={setContextState}>
        <Incrementor />
        <Parent />
      </ActionsContext.Provider>
    </ViewContext.Provider>
  )
}

function Incrementor() {
  const setContextState = useContext(ActionsContext);

  const increment = () => {
    console.clear();
    setContextState(p => p + 1);
  }

  return <button onClick={increment}>increment</button>;
}

function Parent() {
  const contextState = useContext(ViewContext);

  useEffect(() => {
    console.log(contextState, ' - Parent Mounted');
    return () => console.log(contextState, ' - Parent Unmounted');
  }, [contextState]);

  return (
    <div>
      <p>This is the parent: {contextState}</p>
      {contextState % 2
        ? <ConditionalChild />
        : null}
    </div>
  );
}

function ConditionalChild() {
  const contextState = useContext(ViewContext);

  useEffect(() => {
    console.log(contextState, ' -  Child Mounted');
    return () => console.log(contextState, ' -  Child Unmounted');
  }, [contextState]);

  return (
    <div>
      <p>This is the child: {contextState}</p>
    </div>
  );
}

ReactDOM.render(
  <MyContainer />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

<div id="root"></div>

【讨论】:

    猜你喜欢
    • 2021-12-01
    • 2019-01-08
    • 2021-03-05
    • 2020-10-24
    • 2021-01-27
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多