Nowsza odpowiedź z przykładem, który wykorzystuje React.useState
Zalecane jest utrzymywanie stanu w komponencie nadrzędnym. Rodzic musi mieć do niego dostęp, ponieważ zarządza nim w dwóch elementach potomnych. Przeniesienie go do stanu globalnego, takiego jak zarządzanego przez Redux, nie jest zalecane z tego samego powodu, dla którego zmienna globalna jest ogólnie gorsza niż lokalna w inżynierii oprogramowania.
Gdy stan znajduje się w komponencie nadrzędnym, dziecko może je mutować, jeśli rodzic podaje dziecko valuei onChangemoduł obsługi w rekwizytach (czasami nazywa się to łączem wartości lub wzorcem łącza stanu ). Oto jak zrobiłbyś to z hakami:
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>
}
Cały komponent nadrzędny będzie renderowany ponownie po zmianie danych wejściowych w obiekcie potomnym, co może nie stanowić problemu, jeśli jego ponowne nadanie jest małe / szybkie. Wydajność ponownego renderowania komponentu macierzystego nadal może stanowić problem w ogólnym przypadku (na przykład w dużych formularzach). Ten problem został rozwiązany w twoim przypadku (patrz poniżej).
Wzorzec stanu łącza i brak nadrzędnego renderowania są łatwiejsze do wdrożenia przy użyciu biblioteki innej firmy, takiej jak Hookstate - doładowanieReact.useState obejmuje różne przypadki użycia, w tym również twoją. (Uwaga: Jestem autorem projektu).
Oto jak by to wyglądało z Hookstate. Child1zmieni dane wejściowe, Child2zareaguje na to. Parentbędzie utrzymywać stan, ale nie będzie renderować ponownie po zmianie stanu, tylko Child1i Child2będzie.
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: istnieje wiele innych przykładów obejmujących podobne i bardziej skomplikowane scenariusze, w tym głęboko zagnieżdżone dane, sprawdzanie poprawności stanu, stan globalny z setStatehakiem itp. Istnieje również pełna przykładowa aplikacja online , która wykorzystuje Hookstate i technikę wyjaśnioną powyżej.