Вызывается ли новый API-интерфейс React Context API повторно?

Я пытался понять новый React Context API и играл с ним. Я просто хотел проверить простой случай - что все перерисовывает при обновлении данных для провайдера.

Проверьте этот маленький пример на Codesandbox

Итак, в моем примере у меня есть компонент App - который имеет состояние примерно так -

this.state = {
  number - A random number
  text - A static text
} 

Отсюда я создаю новый контекст реагирования, содержащий number и text из состояния, и передаю значения двум потребителям: Number и Text.

Таким образом, я предполагаю, что если случайное число обновится, оно изменит контекст, и оба компонента должны вызвать повторную визуализацию.

Но на самом деле ценность обновляется, но никакой повторной подачи не происходит.

Итак, мой вопрос -

  1. Обновлены ли они до контекста, не распространяемого через обычные перерисовки? Поскольку я не вижу свои журналы/изменения цвета при изменении контекста.

  2. Все потребители этого провайдера обновлены или нет?

Ответ 1

Обновлены ли они до контекста, не распространяемого через обычные перерисовки? Поскольку я не вижу свои журналы/изменения цвета при изменении контекста.

Обновление значений контекста не запускает повторную визуализацию для всех дочерних элементов поставщика, а только для компонентов, которые визуализируются из Consumer, поэтому в вашем случае, хотя компонент Number содержит Consumer, компонент Number не перерисовывается. а не только функция рендеринга в Consumer и, следовательно, значение изменяется при обновлении контекста. Таким образом, он довольно эффективен, так как не запускает повторные рендеры для всех своих дочерних элементов.

Все потребители этого провайдера обновлены или нет?

Все потребители этого провайдера пройдут цикл обновления, но будет ли ре-рендеринг решен путем сравнения виртуальной DOM. Демонстрацию этого вы можете увидеть в консоли для этой песочницы

РЕДАКТИРОВАТЬ

Вам нужно убедиться, что компоненты отображаются как дочерние компоненты компонента ContextProvider, и вы передаете ему обработчики вместо их рендеринга и обновления состояния ContextProvider, потому что это вызовет повторную визуализацию всех компонентов, которые находятся внутри ContextProvider

Исполнитель использования

App.js

  render() {
    return (
      <AppContext.Provider
        value={{ ...this.state, updateNumber: this.updateNumber }}
      >
        {this.props.children}
      </AppContext.Provider>
    );
  }

index.js

class Data extends React.Component {
  render() {
    return (
      <div>
        <h1>Welcome to React</h1>
        <Number />
        <Text />
        <TestComp />
        <AppContext.Consumer>
          {({ updateNumber }) => (
            <button onClick={updateNumber}>Change Number </button>
          )}
        </AppContext.Consumer>
      </div>
    );
  }
}

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

Меньше использования Performant

App.js

class App extends Component {
  constructor() {
    super();
    this.state = {
      number: Math.random() * 100,
      text: "testing context api"
    };
  }

  updateNumber = () => {
    const randomNumber = Math.random() * 100;
    this.setState({ number: randomNumber });
  };

  render() {
    return (
      <AppContext.Provider value={this.state}>
        <div>
          <h1>Welcome to React</h1>
          <Number />
          <Text />
          <TestComp />
          <button onClick={this.updateNumber}>Change Number </button>
        </div>
      </AppContext.Provider>
    );
  }
}