使用useContext不必要地重新渲染

时间:2020-02-19 20:15:44

标签: javascript reactjs react-hooks

在此example

function App() {
  const [value1, dispatch1] = useReducer(reducer, initialState1);
  const [value2, dispatch2] = useReducer(reducer, initialState2);

  return (
    <React.Fragment>
      <button
        onClick={() => {
          dispatch1({ type: "setFirstName", firstName: "nick" });
        }}
      >
        change1
      </button>
      <button
        onClick={() => {
          dispatch2({ type: "setFamilyName", familyName: "fname" });
        }}
      >
        change2
      </button>
      <JediContext1.Provider value={value1}>
        <Display1 />
      </JediContext1.Provider>
      <JediContext2.Provider value={value2}>
        <Display2 />
      </JediContext2.Provider>
    </React.Fragment>
  );
}

我为here的每个推荐使用了两个上下文。但是我可能有一个误解,也许github问题是指另一种情况? 因为它似乎无法解决我的问题。

上面的代码存在问题,如果我单击change1按钮,它会更改value1,组件Display2 也将重新呈现,甚至不消耗 { {1}}。

实际上,这对我来说是有意义的,因为我更改了App中的状态,因此它将重新呈现其所有子级。但是,我不理解github链接中对推荐的使用,因为它没有不能在这里解决我的问题吗?

如果您有大型应用程序和root上下文提供者说,这可能是性能问题。

2 个答案:

答案 0 :(得分:3)

通常,并非总是如此,您想记住您的提供商的Display1来避免这种情况。 在这种情况下,Display2const Display1 = React.memo(() => <Whatever />) 可以是PureComponent,也可以只是

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mobile_navigation"
    app:startDestination="@id/destination_lists">

您链接的github问题是另一个问题:您的提供者包含很多数据,并且您只希望订阅其中的一部分。在某些情况下,您更新了上下文的值,它将重新呈现未使用该值的使用者。在这种情况下,您可能只想将其拆分为多个上下文,如所解释。但这不是您的问题。

答案 1 :(得分:1)

尝试memoizing both components,以便它们仅在其本地状态更改时呈现:

const MemoDisplay = React.memo(Display1);
const MemoDisplay2 = React.memo(Display2);

function App() {
  ...
  return (
    <React.Fragment>
      ...
      <JediContext1.Provider value={value1}>
        <MemoDisplay />
      </JediContext1.Provider>
      <JediContext2.Provider value={value2}>
        <MemoDisplay2 />
      </JediContext2.Provider>
    </React.Fragment>
  );
}

Edit React Hooks - useContext()

注意日志,此后没有不必要的渲染。