#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
в вашем случае), который хранит все состояние и передает его поставщику. Если состояние большое, то этот компонент управляет множеством несвязанной логики. У вас есть какие-нибудь идеи, как провести рефакторинг, чтобы эти логики были разделены (в отдельных компонентах, отдельных модулях …)?