【问题标题】:Update React Context without re-rendering the component making the update在不重新渲染进行更新的组件的情况下更新 React Context
【发布时间】:2020-09-14 05:22:32
【问题描述】:

我有一个上下文和 2 个组件:一个是显示上下文中的内容,另一个是更新它。

通过在更新程序组件中包含以下代码,它将在更改上下文时重新渲染。

const [, setArray] = React.useContext(context);
setArray(prevArray => { return [...prevArray, []] }

这意味着无限重新渲染。我需要避免这种情况。由于更新程序不使用上下文中的数据,因此不应更新。

完整示例:我正在存储和显示有关组件的 Profiler 数据。

https://codesandbox.io/s/update-react-context-without-re-rendering-the-component-making-the-update-k8ogr?file=/src/App.js

const context = React.createContext();

const Provider = props => {
  const [array, setArray] = React.useState([]);

  const value = React.useMemo(() => [array, setArray], [array]);

  return <context.Provider value={value} {...props} />;
};

const Metrics = () => {
  const [array] = React.useContext(context);

  return <TextareaAutosize value={JSON.stringify(array, null, 2)} />;
};

const Component = () => {
  const [, setArray] = React.useContext(context);

  const onRenderCallback = (id, _phase, actualDuration) => {
    setArray(prevArray => {
      return [...prevArray, [id, actualDuration]];
    });
  };

  return (
    <React.Profiler id="1" onRender={onRenderCallback}>
      <div />
    </React.Profiler>
  );
};

export default function App() {
  return (
    <div className="App">
      <Provider>
        <Metrics />
        <Component />
      </Provider>
    </div>
  );
}

【问题讨论】:

    标签: javascript reactjs react-hooks react-context


    【解决方案1】:

    这是我使用以下文章得出的结论:https://kentcdodds.com/blog/how-to-optimize-your-context-value

    使用 2 个上下文,一个用于存储状态,一个用于更新状态:

    const stateContext = React.createContext();
    const updaterContext = React.createContext();
    
    const array = React.useContext(stateContext);
    const setArray = React.useContext(updaterContext);
    

    完整示例: https://codesandbox.io/s/solution-update-react-context-without-re-rendering-the-component-making-the-update-yv0gf?file=/src/App.js

    import React from "react";
    import "./styles.css";
    import TextareaAutosize from "react-textarea-autosize";
    
    // https://kentcdodds.com/blog/how-to-optimize-your-context-value
    const stateContext = React.createContext();
    const updaterContext = React.createContext();
    
    const Provider = props => {
      const [array, setArray] = React.useState([]);
    
      return (
        <stateContext.Provider value={array}>
          <updaterContext.Provider value={setArray}>
            {props.children}
          </updaterContext.Provider>
        </stateContext.Provider>
      );
    };
    
    const useUpdaterContext = () => {
      return React.useContext(updaterContext);
    };
    
    const Metrics = () => {
      const array = React.useContext(stateContext);
    
      return <TextareaAutosize value={JSON.stringify(array, null, 2)} />;
    };
    
    const Component = () => {
      const setArray = useUpdaterContext();
    
      const onRenderCallback = (id, _phase, actualDuration) => {
        setArray(prevArray => [...prevArray, [id, actualDuration]]);
      };
    
      return (
        <React.Profiler id="1" onRender={onRenderCallback}>
          <div />
        </React.Profiler>
      );
    };
    
    export default function App() {
      return (
        <div className="App">
          <Provider>
            <Metrics />
            <Component />
          </Provider>
        </div>
      );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-18
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-18
      • 2017-06-17
      • 1970-01-01
      相关资源
      最近更新 更多