【问题标题】:Avoiding rerenders when using React Context使用 React Context 时避免重新渲染
【发布时间】:2020-06-04 19:09:32
【问题描述】:

Codesandbox here

我将上下文用于各种组件的状态,在这种情况下,选中了哪个复选框,并且正在使用该组件来改变该组件的状态。但是,只需单击一个复选框,所有四个组件(复选框)都会重新呈现。在挂钩和改变上下文时如何防止这种重新渲染?谢谢。

index.tsx:

import * as React from "react";
import ReactDOM from "react-dom";
import { ContextProvider, useMyContext } from "./context";
import "./styles.css";

const Checkbox: React.FC<{ id: number }> = ({ id }) => {
  React.useEffect(() => console.log(`Checkbox ${id} Render`));

  const { setValue, value } = useMyContext();

  return (
    <input
      onClick={() => setValue(id)}
      checked={id === value}
      type="checkbox"
    />
  );
};

const Container: React.FC = () => {
  React.useEffect(() => console.log("Container Render"));

  return (
    <div>
      {[0, 1, 2, 3].map(id => (
        <Checkbox id={id} />
      ))}
    </div>
  );
};

const App: React.FC = () => {
  return (
    <ContextProvider>
      <Container />
    </ContextProvider>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

context.tsx:

import * as React from "react";

interface ContextState {
  setValue: (id: number) => void;
  value: number;
}

const initialContextState: ContextState = {
  setValue: () => {},
  value: 0
};

const Context = React.createContext<ContextState>(initialContextState);

export const ContextProvider: React.FC = (props: object) => {
  const [value, setValue] = React.useState<number>(0);

  return (
    <Context.Provider
      value={{
        setValue,
        value
      }}
      {...props}
    />
  );
};

export const useMyContext = (): ContextState => React.useContext(Context);

【问题讨论】:

  • 请在问题中输入minimal reproducible example
  • 请花一点时间来真正阅读我发布的内容。这是一个链接,而不是 MRE。
  • @jonrsharpe 更新谢谢

标签: html reactjs typescript


【解决方案1】:

您无法阻止上下文消耗组件的重新呈现(在您的示例中为Checkbox) - 更新上下文值时强制重新呈现正是 Context API 的工作方式,您不能应用任何“选择性” ' 给它。

可以做的就是将消耗组件的实际内容中昂贵的部分提取到用React.memo 包裹的子组件中(或者将其内联为包裹在useMemo 钩子 - docs),从上下文中获取您需要的值并将这些值作为道具传递给该子组件/依赖项到 useMemo 部分。

内置的记忆功能将“正常工作”,并且不会为实际值不更新的复选框重新渲染子组件(昂贵的部分),因为相关的道具不会改变。

使用这样的记忆可以解决您需要解决的任何实际性能问题,但只是提醒您,在 90% 的情况下,这些东西并不重要。在以这种方式重构组件之前,测试和确定性能实际上是一个问题。通常根本不值得额外的间接来解决一个非问题!

【讨论】:

    【解决方案2】:

    Here你可以找到类似的例子,

    使用这个库react-hooks-in-callback 你可以过滤掉所有不必要的重新渲染

    查看结果Here

    【讨论】:

      猜你喜欢
      • 2018-12-21
      • 2020-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-21
      • 2016-12-06
      • 1970-01-01
      相关资源
      最近更新 更多