React Context API работает медленно - PullRequest
0 голосов
/ 13 января 2019

Я экспериментирую с новым Context API и хуками. Я создал приложение с боковой панелью (древовидная структура), нижним колонтитулом и страницей основного контента. У меня есть провайдер контекста

const ContextProvider: FunctionComponent = (props) => {

const [selected, setSelected] = useState(undefined);
const [treeNodes, setTreeNodes] = useState([]);

return (
    <MyContext.Provider
        value={{
            actions: {
                setSelected,
                setTreeNodes
            },
            selected,
            treeNodes
        }}
    >
        {props.children}
    </MyContext.Provider>
);

Я являюсь моим компонентом контента. У меня есть DetailsList (интерфейс Office Fabric), содержащий около 1000 элементов. Когда я нажимаю на элемент в списке, я хочу обновить выбранный элемент в контексте. Это работает, но это действительно медленно. Для выбора элемента в списке требуется около 0,5-1 секунды. Список виртуализирован. Я попробовал это на сборке производства. Все немного лучше, но при нажатии на список есть заметная задержка. Нижний колонтитул использует myContext для отображения информации о выбранном элементе.

Вот немного кода из моего компонента

const cntx = useContext(MyContext);

const onClick = (item) => {
    cntx.actions.setSelected(item);
};

Я неправильно использую контекст?

Я создал образец песочницы для демонстрации. Вы можете прокрутить до примерно 100-го индекса и щелкнуть пару раз, чтобы увидеть, как он перестает отвечать.

https://codesandbox.io/s/0m4nqxp4m0

Это проблема с Fabric DetailsList? Это повторяется много раз? Я полагаю, что проблема связана со «сложным» компонентом DatePicker, но я не понимаю, почему DetailsList переопределяется? Он не использует никаких свойств контекста в функции рендеринга. Я ожидаю, что только компонент нижнего колонтитула будет перерисовываться при каждом изменении контекста

1 Ответ

0 голосов
/ 10 апреля 2019

Предостережение Поскольку контекст использует ссылочную идентификацию, чтобы определить, когда необходимо выполнить повторную визуализацию, существуют некоторые ошибки, которые могут вызвать непреднамеренную визуализацию у потребителей при повторной визуализации родительского объекта поставщика. Например, приведенный ниже код будет перерисовывать всех потребителей каждый раз, когда провайдер выполняет повторную визуализацию, поскольку для значения всегда создается новый объект:

class App extends React.Component {
  render() {
    return (
      <Provider value={{something: 'something'}}>
        <Toolbar />
      </Provider>
    );
  }
}
To get around this, lift the value into the parent’s state:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: {something: 'something'},
    };
  }

  render() {
    return (
      <Provider value={this.state.value}>
        <Toolbar />
      </Provider>
    );
  }
}

https://reactjs.org/docs/context.html#caveats

...