Более свежий ответ с примером, который использует React.useState
Сохранение состояния в родительском компоненте является рекомендуемым способом. Родитель должен иметь доступ к нему, поскольку он управляет им через два дочерних компонента. Перемещение его в глобальное состояние, подобное тому, которым управляет Redux, не рекомендуется по той же причине, почему глобальная переменная хуже, чем локальная в целом в разработке программного обеспечения.
Когда состояние находится в родительском компоненте, дочерний элемент может изменить его, если родительский элемент передает дочерний элемент value
и onChange
обработчик в реквизитах (иногда это называется ссылкой на значение или шаблоном ссылки на состояние ). Вот как бы вы сделали это с помощью хуков:
function Parent() {
var [state, setState] = React.useState('initial input value');
return <>
<Child1 value={state} onChange={(v) => setState(v)} />
<Child2 value={state}>
</>
}
function Child1(props) {
return <input
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
}
function Child2(props) {
return <p>Content of the state {props.value}</p>
}
Весь родительский компонент будет повторно отображаться при изменении входных данных в дочернем элементе, что может не быть проблемой, если родительский компонент слишком мал / быстр для повторной визуализации. Производительность повторного рендеринга родительского компонента все еще может быть проблемой в общем случае (например, большие формы). Это решаемая проблема в вашем случае (см. Ниже).
Шаблон связи состояний и отсутствие родительского повторного рендеринга проще реализовать с помощью сторонней библиотеки, такой как Hookstate - с наддувомReact.useState
чтобы охватить различные варианты использования, включая ваш. (Отказ от ответственности: я автор проекта).
Вот как это будет выглядеть с Hookstate. Child1
изменит вход, Child2
отреагирует на это. Parent
будет удерживать состояние, но не будет повторно выполнять рендеринг при изменении состояния, только Child1
и Child2
будет.
import { useStateLink } from '@hookstate/core';
function Parent() {
var state = useStateLink('initial input value');
return <>
<Child1 state={state} />
<Child2 state={state}>
</>
}
function Child1(props) {
// to avoid parent re-render use local state,
// could use `props.state` instead of `state` below instead
var state = useStateLink(props.state)
return <input
value={state.get()}
onChange={e => state.set(e.target.value)}
/>
}
function Child2(props) {
// to avoid parent re-render use local state,
// could use `props.state` instead of `state` below instead
var state = useStateLink(props.state)
return <p>Content of the state {state.get()}</p>
}
PS: здесь есть еще много примеров, охватывающих аналогичные и более сложные сценарии, включая глубоко вложенные данные, проверку состояния, глобальное состояние с setState
перехватом и т. Д. Кроме того, в Интернете есть полный пример приложения , в котором используется Hookstate и методика, описанная выше.