当通过钩子更新全局状态时,React 组件以什么顺序重新渲染?

时间:2021-06-03 10:58:52

标签: reactjs react-hooks

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

<Parent>
  <Child />
</Parent>

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

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

1 个答案:

答案 0 :(得分:0)

这是一个记录父子进程挂载/卸载的片段。 Child 仅在状态值为奇数时呈现。两个组件都访问相同的上下文。

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>