Могу ли я отслеживать изменения вложенных объектов в контексте React?

#reactjs #react-context

#reactjs ( реакция ) #реагировать-контекст #reactjs

Вопрос:

Воспроизведение:

 const defaultState = {
  value: 1;
  increment() {
      this.value;
  }
}

const AppContext = React.createContext({ myState: defaultState });
  

В компоненте React

 class MyComponent extends Component {
  static contextType = AppContext;

  componentDidMount() {
    const { myState } = this.context;
    myState.increment();
  }

  render() {
    const { myState } = this.context;
    return <p>{myState.value}</p>;
  }
}
  

Ожидается

Шоу 2 .

Фактический

Шоу 1 .

Как я могу обновить компонент React при изменении внутренних полей в моем состоянии?

Комментарии:

1. Как прекрасно описывает ваша переменная defaultState , это состояние по умолчанию, которое будет использоваться только как запасной вариант и не будет изменено. Чтобы добиться желаемого поведения, вам нужно будет предоставить фактическое обновляемое значение для вашего контекста, как описано в документах .

Ответ №1:

Аргумент, заданный для createContext , является значением контекста по умолчанию, если над потребителем в дереве нет Provider компонента. Изменение этого объекта по умолчанию не приведет к повторному отображению потребителей контекста.

Вместо этого вы могли бы поместить Provider в компонент, который имеет value состояние as, и increment метод, который обновляет состояние, и передать их через контекст с value поддержкой.

Пример

 const AppContext = React.createContext();

class App extends React.Component {
  state = {
    value: 1
  };

  increment = () => {
    this.setState(({ value }) => ({ value: value   1 }));
  };

  render() {
    const { increment } = this;

    return (
      <AppContext.Provider value={{ myState: { ...this.state, increment } }}>
        <MyComponent />
      </AppContext.Provider>
    );
  }
}

class MyComponent extends React.Component {
  static contextType = AppContext;

  componentDidMount() {
    this.context.myState.increment();
  }

  render() {
    const { myState } = this.context;
    return <p>{myState.value}</p>;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>  

Комментарии:

1. Спасибо. Косметический запрос: мой контекст довольно большой, this.context.increment() был бы переименован в this.context.myStateIncrement() , такой же, как myStateDecrement и myStateValue . Нет никакого способа перегруппировать их под context.myState.{value, decrement, increment} , верно?

2. @amaurymartiny Всегда пожалуйста! Я обновил ответ с вашим запросом.

3. Спасибо. Целый компонент React кажется мне немного излишним для хранения одного значения. Но если это так и должно быть сделано, пусть будет так.

4. @amaurymartiny Да, рендеринг Provider — это способ сделать это. Вы могли бы просто иметь одно единственное Provider со всеми вашими значениями контекста вместо множества разных, если хотите.

5. Повторите ваш последний комментарий: это то, что я хочу, один Provider файл, который можно было бы использовать static contextType = AppContext (см. мой первоначальный вопрос). Есть один компонент ( App в вашем случае), который хранит все состояние и передает его поставщику. Если состояние большое, то этот компонент управляет множеством несвязанной логики. У вас есть какие-нибудь идеи, как провести рефакторинг, чтобы эти логики были разделены (в отдельных компонентах, отдельных модулях …)?