Próbuję znaleźć właściwy sposób zdefiniowania niektórych składników, które mogłyby być używane w ogólny sposób:
<Parent>
<Child value="1">
<Child value="2">
</Parent>
Istnieje oczywiście logika renderowania między komponentami nadrzędnymi i podrzędnymi, co można sobie wyobrazić <select>
i <option>
jako przykład tej logiki.
To jest fikcyjna implementacja na potrzeby pytania:
var Parent = React.createClass({
doSomething: function(value) {
},
render: function() {
return (<div>{this.props.children}</div>);
}
});
var Child = React.createClass({
onClick: function() {
this.props.doSomething(this.props.value); // doSomething is undefined
},
render: function() {
return (<div onClick={this.onClick}></div>);
}
});
Pytanie brzmi: ilekroć użyjesz {this.props.children}
do zdefiniowania elementu opakowania, w jaki sposób przekazujesz jakąś właściwość wszystkim jego potomkom?
javascript
reactjs
react-jsx
plus-
źródło
źródło
Odpowiedzi:
Klonowanie dzieci za pomocą nowych rekwizytów
Możesz użyć React.Children do iteracji nad dziećmi, a następnie sklonować każdy element z nowymi rekwizytami (płytko scalone) za pomocą React.cloneElement, np .:
Fiddle: https://jsfiddle.net/2q294y43/2/
Wywoływanie dzieci jako funkcja
Możesz także przekazywać rekwizyty dzieciom z rekwizytami renderującymi . W tym podejściu dzieci (które mogą być
children
innymi nazwami rekwizytów) to funkcja, która może zaakceptować argumenty, które chcesz przekazać, i zwraca dzieci:Zamiast
<React.Fragment>
lub po prostu<>
możesz również zwrócić tablicę, jeśli wolisz.Fiddle: https://jsfiddle.net/ferahl/y5pcua68/7/
źródło
value
przekazana dodoSomething
została utracona.Aby uzyskać nieco czystszy sposób, spróbuj:
Edycja: Aby używać z wieloma pojedynczymi dziećmi (dziecko musi być komponentem), możesz to zrobić. Testowane w 16.8.6
źródło
this.props.children
) docloneElement
..., które oczekuje ... elementu.React.Children.only
funkcja zwraca jedyne dziecko lub zgłasza wyjątek, jeśli jest ich wiele (nie istniałoby, gdyby nie było przypadku użycia).Spróbuj tego
Działa dla mnie za pomocą Reag-15.1.
źródło
React.cloneElement()
bezpośrednio, nie otaczając go<div>
tagami? Bo co jeśli dziecko jest<span>
(lub czymś innym) i chcemy zachować jego typ elementu tagu?React.cloneElement(React.Children.only(this.props.children), {...this.props})
co spowoduje błąd, jeśli zostanie przekazane więcej niż jedno dziecko. Więc nie musisz zawijać div.let {children, ...acyclicalProps} = this.props
a następnieReact.cloneElement(React.Children.only(children), acyclicalProps)
.Przekaż rekwizyty dzieciom.
Zobacz wszystkie pozostałe odpowiedzi
Przekaż wspólne, globalne dane przez drzewo komponentów poprzez kontekst
Oświadczenie: To jest zaktualizowana odpowiedź, poprzednia użyła starego kontekstowego interfejsu API
Opiera się na zasadzie konsument / dostarcz. Najpierw utwórz kontekst
Następnie użyj przez
i
Pełny przykład, pseudo-kod.
1 https://facebook.github.io/react/docs/context.html
źródło
this.context
) - nie magicznie połączyła kontekstu z rekwizytami. Trzeba było celowo ustawić i użyć kontekstu, co jest zupełnie inną rzeczą.Przekazywanie rekwizytów zagnieżdżonym dzieciom
Wraz z aktualizacją do React 16.6 można teraz używać React.createContext i contextType .
źródło
this
kontekstuMożesz użyć
React.cloneElement
, lepiej wiedzieć, jak to działa, zanim zaczniesz używać go w swojej aplikacji. Został wprowadzonyReact v0.13
, czytaj dalej, aby uzyskać więcej informacji, więc coś z tą pracą dla Ciebie:Przynieś wiersze z dokumentacji React, aby zrozumieć, jak to wszystko działa i jak możesz z nich skorzystać:
więcej tutaj ...
źródło
Najlepszym sposobem, który pozwala na przeniesienie własności jest
children
jak funkcjaPrzykład:
źródło
nested components
. React nie ma zagnieżdżonych wzorów, tylko kompozycje. Tak, dzieci muszą być funkcją, nie ma żadnych konfliktów, ponieważ jest to poprawne dziecko JSX. Czy możesz podać przykładnesting components
?<Parent>{props => <Nest><ChildComponent /></Nest>}</Parent>
zająć się (nie pracować),<Parent><Nest>{props => <ChildComponent />}</Nest></Parent>
więc zgadzam się, że to najlepsza odpowiedźTypeError: children is not a function
Musiałem naprawić zaakceptowaną odpowiedź powyżej, aby działała przy użyciu tej zamiast tego wskaźnika. W zakresie funkcji mapy nie zdefiniowano funkcji doSomething .
Aktualizacja: ta poprawka dotyczy ECMAScript 5, w ES6 nie ma potrzeby w var that = this
źródło
bind()
doSomething
wziął przedmiot, jakdoSomething: function(obj) { console.log(obj) }
w Dzieciątku, do którego byśthis.props.doSomething(obj)
się wylogował"obj"
apply
metodę. użyciebind()
funkcji renderowania spowoduje utworzenie nowej funkcji za każdym razem, gdy wywoływana jest metoda renderowania.Czystszy sposób, biorąc pod uwagę jedno lub więcej dzieci
źródło
this.props
. Zasadniczo zalecałbym klonowanie tylko za pomocą określonych rekwizytów, a nie całego shebang.{...this.props}
nie działało dla mnie, czy sposób jest{...child.props}
poprawny?React.Children.map(children, child => React.cloneElement(child, props))
Żadna z odpowiedzi nie rozwiązuje problemu posiadania dzieci, które NIE są komponentami React, takimi jak ciągi tekstowe. Obejściem może być coś takiego:
źródło
Nie potrzebujesz już
{this.props.children}
. Teraz można owinąć dziecko przy użyciu komponenturender
wRoute
i przekazać swoje rekwizyty jak zwykle:źródło
Parent.jsx:
Child.jsx:
i main.jsx:
patrz przykład tutaj: https://plnkr.co/edit/jJHQECrKRrtKlKYRpIWl?p=preview
źródło
Może ta funkcja może Ci się przydać, chociaż wiele osób uważa ją za anty-wzór, nadal można jej użyć, jeśli wiesz, co robisz i dobrze projektujesz swoje rozwiązanie.
Funkcja jako elementy potomne
źródło
Jeśli masz wiele dzieci, którym chcesz przekazać rekwizyty , możesz to zrobić w ten sposób, używając React.Children.map:
Jeśli twój komponent ma tylko jedno dziecko, nie ma potrzeby mapowania, możesz po prostu sklonować element:
źródło
Zgodnie z dokumentacją
cloneElement()
Więc cloneElement jest tym, czego użyłbyś do zapewnienia niestandardowych rekwizytów dzieciom. Jednak komponent może zawierać wiele elementów podrzędnych i należy go zapętlić. Co sugerują inne odpowiedzi, możesz zmapować je za pomocą
React.Children.map
. Jednak wReact.Children.map
przeciwieństwie doReact.cloneElement
zmian, klucze dołączanego elementu i dodatkowe.$
jako przedrostek. Sprawdź to pytanie, aby uzyskać więcej informacji: React.cloneElement wewnątrz React.Children.map powoduje zmianę kluczy elementówJeśli chcesz tego uniknąć, powinieneś zamiast tego wybrać
forEach
funkcję podobną doźródło
Oprócz odpowiedzi @ i_rest, w ten sposób sklonowałem dzieci i dodałem klasę.
źródło
Myślę, że rekwizyt renderowania jest odpowiednim sposobem na poradzenie sobie z tym scenariuszem
Zezwalasz rodzicowi na dostarczenie niezbędnych rekwizytów używanych w komponencie potomnym, refaktoryzując kod rodzica, aby wyglądał mniej więcej tak:
Następnie w komponencie potomnym można uzyskać dostęp do funkcji dostarczonej przez rodzica w ten sposób:
Teraz struktura fianl będzie wyglądać następująco:
źródło
Metoda 1 - klonowanie dzieci
Metoda 2 - użyj kontekstu kompozycyjnego
Kontekst umożliwia przekazanie rekwizytu do głębokiego komponentu potomnego bez jawnego przekazywania go jako rekwizytu przez komponenty pomiędzy nimi.
Kontekst ma wady:
Korzystanie z kontekstu kompozycyjnego
źródło
{children}:{children:ReactNode}
?"children"
jest typuReactNode
Najszybszy sposób to zrobić:
źródło
Każdy, kto ma pojedynczy element potomny, powinien to zrobić.
źródło
Czy tego potrzebujesz?
źródło
Z jakiegoś powodu React.children nie pracował dla mnie. To działało dla mnie.
Chciałem po prostu dodać klasę do dziecka. podobnie jak zmiana rekwizytu
Sztuką jest React.cloneElement . Możesz przekazać dowolny rekwizyt w podobny sposób
źródło
Renderowanie rekwizytów jest najdokładniejszym podejściem do tego problemu. Zamiast przekazywać komponent podrzędny do komponentu nadrzędnego jako rekwizyty potomne, pozwól rodzicowi renderować komponent podrzędny ręcznie. Renderowanie to wbudowane rekwizyty w reakcji, która przyjmuje parametr funkcji. W tej funkcji możesz pozwolić komponentowi nadrzędnemu na renderowanie dowolnych parametrów za pomocą parametrów niestandardowych. Zasadniczo robi to samo, co rekwizyty dziecięce, ale można go lepiej dostosowywać.
Przykład w codepen
źródło
Podczas korzystania z komponentów funkcjonalnych często
TypeError: Cannot add property myNewProp, object is not extensible
pojawia się błąd przy próbie ustawienia nowych właściwościprops.children
. Można to obejść poprzez klonowanie rekwizytów, a następnie klonowanie samego dziecka za pomocą nowych rekwizytów.źródło