Powiedzmy, że mam składnik widoku, który ma renderowanie warunkowe:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
MyInput wygląda mniej więcej tak:
class MyInput extends React.Component {
...
render(){
return (
<div>
<input name={this.props.name}
ref="input"
type="text"
value={this.props.value || null}
onBlur={this.handleBlur.bind(this)}
onChange={this.handleTyping.bind(this)} />
</div>
);
}
}
Powiedzmy, że employed
to prawda. Za każdym razem, gdy przełączam go na false, a inny widok renderuje się, tylko unemployment-duration
jest ponownie inicjowany. unemployment-reason
Zostaje również wstępnie wypełniona wartością z job-title
(jeśli wartość została podana przed zmianą warunku).
Jeśli zmienię znaczniki w drugiej procedurze renderowania na coś takiego:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Wygląda na to, że wszystko działa dobrze. Wygląda na to, że React po prostu nie rozróżnia „tytułu stanowiska” i „powodu bezrobocia”.
Proszę, powiedz mi, co robię źle ...
javascript
reactjs
o01
źródło
źródło
data-reactid
każdym z elementówMyInput
(lubinput
, jak widać w DOM), przed i poemployed
przełączeniu?<div>
. Tedata-reactid
atrybuty wydaje się być różne na obu div owijania i polu tekstowym.job-title
wejście otrzymuje iddata-reactid=".0.1.1.0.1.0.1"
, podczas gdyunemployment-reason
wejście otrzymuje iddata-reactid=".0.1.1.0.1.2.1"
unemployment-duration
?reactid
atrybuty są identycznejob-title
iunemployment-reason
, podczas gdy w drugim przypadku (przy rozpiętości diff) są one różne.unemployment-duration
tejreactid
atrybutu jest zawsze wyjątkowy.Odpowiedzi:
Prawdopodobnie dzieje się tak, że React uważa, że między renderowaniami jest dodawany tylko jeden znak
MyInput
(unemployment-duration
). W związku z tymjob-title
nigdy nie jest zastępowane przezunemployment-reason
, co jest również powodem zamiany wstępnie zdefiniowanych wartości.Kiedy React wykona różnicę, określi, które komponenty są nowe, a które stare na podstawie ich
key
właściwości. Jeśli w kodzie nie ma takiego klucza, wygeneruje własny.Powodem, dla którego ostatni udostępniony fragment kodu działa, jest to, że React zasadniczo musi zmienić hierarchię wszystkich elementów podrzędnym
div
i uważam, że spowodowałoby to ponowne renderowanie wszystkich dzieci (i dlatego to działa). Gdybyś dodał naspan
dole zamiast na górze, hierarchia poprzednich elementów nie zmieniłaby się, a te elementy nie byłyby ponownie renderowane (i problem utrzymywałby się).Oto, co mówi oficjalna dokumentacja React :
Powinieneś być w stanie to naprawić, dostarczając samodzielnie unikalny
key
element rodzicowidiv
lub wszystkimMyInput
elementom.Na przykład:
LUB
Teraz, gdy React wykona
divs
różnicę , zobaczy, że są różne i ponownie wyrenderuje je, w tym wszystkie jego dzieci (pierwszy przykład). W 2. przykładzie diff będzie sukcesjob-title
, aunemployment-reason
ponieważ mają teraz różne klucze.Możesz oczywiście używać dowolnych kluczy, o ile są unikalne.
Aktualizacja z sierpnia 2017 r
Aby uzyskać lepszy wgląd w działanie kluczy w React, zdecydowanie polecam przeczytanie mojej odpowiedzi na temat Zrozumienie unikalnych kluczy w React.js .
Aktualizacja z listopada 2017 r
Ta aktualizacja powinna zostać opublikowana jakiś czas temu, ale używanie literałów ciągów w programie
ref
jest obecnie przestarzałe. Na przykładref="job-title"
powinien teraz zamiastref={(el) => this.jobTitleRef = el}
(na przykład). Zobacz moją odpowiedź na ostrzeżenie o wycofaniu przy użyciu this.refs, aby uzyskać więcej informacji.źródło
it will determine which components are new and which are old based on their key property.
- to był ... klucz ... dla mojego zrozumieniaZmień klucz komponentu.
Komponent zostanie odmontowany, a po zmianie klucza zostanie zamontowana nowa instancja komponentu.
edycja : Udokumentowano, że prawdopodobnie nie potrzebujesz stanu pochodnego :
źródło
Użyj
setState
w swoim widoku, aby zmienićemployed
właściwość stanu. To jest przykład silnika renderującego React.źródło
Pracuję nad Crudem dla mojej aplikacji. W ten sposób to zrobiłem Dostałem Reactstrap jako moją zależność.
Jest tam kilka haków reakcyjnych
źródło