Обновить React Context без повторного рендеринга компонента, выполняющего обновление - PullRequest
0 голосов
/ 27 мая 2020

У меня есть контекст и 2 компонента: один отображает то, что находится в контексте, другой обновляет его.

Имея следующий код в компоненте средства обновления, он будет повторно отображаться при изменении контекста .

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

Это означает, что infit ie перерисовывает. Мне нужно этого избежать. Поскольку средство обновления не использует данные в контексте, оно не должно обновляться.

Полный пример: я сохраняю и отображаю данные профилировщика о компоненте.

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>
  );
}

1 Ответ

0 голосов
/ 27 мая 2020

Это то, что я придумал, используя следующую статью: 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>
  );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...