Nie byłem zadowolony z żadnego z przedstawionych tutaj rozwiązań. W rzeczywistości istnieje bardzo proste rozwiązanie, które można wykonać przy użyciu czystego Javascript bez polegania na niektórych funkcjach React innych niż podstawowy obiekt rekwizytów - i daje to korzyść komunikacji w obu kierunkach (rodzic -> dziecko, dziecko -> rodzic). Musisz przekazać obiekt z komponentu nadrzędnego do komponentu podrzędnego. Ten obiekt nazywam „odniesieniem dwukierunkowym” lub w skrócie biRef. Zasadniczo obiekt zawiera odwołanie do metod w obiekcie nadrzędnym, które rodzic chce udostępnić. Komponent potomny dołącza metody do obiektu, który rodzic może wywołać. Coś takiego:
// Parent component.
function MyParentComponent(props) {
function someParentFunction() {
// The child component can call this function.
}
function onButtonClick() {
// Call the function inside the child component.
biRef.someChildFunction();
}
// Add all the functions here that the child can call.
var biRef = {
someParentFunction: someParentFunction
}
return <div>
<MyChildComponent biRef={biRef} />
<Button onClick={onButtonClick} />
</div>;
}
// Child component
function MyChildComponent(props) {
function someChildFunction() {
// The parent component can call this function.
}
function onButtonClick() {
// Call the parent function.
props.biRef.someParentFunction();
}
// Add all the child functions to props.biRef that you want the parent
// to be able to call.
props.biRef.someChildFunction = someChildFunction;
return <div>
<Button onClick={onButtonClick} />
</div>;
}
Inną zaletą tego rozwiązania jest to, że można dodać o wiele więcej funkcji w obiekcie nadrzędnym i podrzędnym, przekazując je z obiektu nadrzędnego dziecku przy użyciu tylko jednej właściwości.
Ulepszenie w stosunku do powyższego kodu polega na tym, aby nie dodawać funkcji nadrzędnej i podrzędnej bezpośrednio do obiektu biRef, ale raczej do elementów podrzędnych. Funkcje nadrzędne należy dodać do elementu o nazwie „rodzic”, a funkcje podrzędne należy dodać do elementu o nazwie „dziecko”.
// Parent component.
function MyParentComponent(props) {
function someParentFunction() {
// The child component can call this function.
}
function onButtonClick() {
// Call the function inside the child component.
biRef.child.someChildFunction();
}
// Add all the functions here that the child can call.
var biRef = {
parent: {
someParentFunction: someParentFunction
}
}
return <div>
<MyChildComponent biRef={biRef} />
<Button onClick={onButtonClick} />
</div>;
}
// Child component
function MyChildComponent(props) {
function someChildFunction() {
// The parent component can call this function.
}
function onButtonClick() {
// Call the parent function.
props.biRef.parent.someParentFunction();
}
// Add all the child functions to props.biRef that you want the parent
// to be able to call.
props.biRef {
child: {
someChildFunction: someChildFunction
}
}
return <div>
<Button onClick={onButtonClick} />
</div>;
}
Umieszczając funkcje nadrzędne i podrzędne w oddzielnych elementach obiektu biRef, będziesz mieć czystą separację między nimi i łatwo zobaczysz, które należą do nadrzędnego lub podrzędnego. Pomaga to również zapobiec przypadkowemu zastąpieniu przez element podrzędny funkcji nadrzędnej, jeśli ta sama funkcja pojawia się w obu.
Ostatnią rzeczą jest to, że jeśli zauważysz, komponent nadrzędny tworzy obiekt biRef za pomocą var, podczas gdy komponent potomny uzyskuje do niego dostęp poprzez obiekt rekwizytów. Może być kuszące, aby nie definiować obiektu biRef w obiekcie nadrzędnym i uzyskiwać do niego dostęp od jego obiektu nadrzędnego za pomocą własnego parametru rekwizytów (co może mieć miejsce w hierarchii elementów interfejsu użytkownika). Jest to ryzykowne, ponieważ dziecko może uważać, że funkcja, którą wywołuje na rodzicu, należy do rodzica, kiedy może faktycznie należeć do dziadka. Nie ma w tym nic złego, o ile jesteś tego świadomy. O ile nie masz powodu, aby wspierać hierarchię poza relacją rodzic-dziecko, najlepiej utworzyć biRef w komponencie nadrzędnym.