Przeglądałem dokumentację haków, kiedy się natknąłem useRef
.
Patrząc na ich przykład…
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
… Wydaje się, że useRef
można go zastąpić createRef
.
function TextInputWithFocusButton() {
const inputRef = createRef(); // what's the diff?
const onButtonClick = () => {
// `current` points to the mounted text input element
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
Po co mi haczyk na referencje? Dlaczego useRef
istnieje?
źródło
useRef
, opublikowaną przez jednego z programistów React. To nie to samo, co zwykłe wywołaniecreateRef
, ponieważcreateRef
nie jest to podpięcie i nie utrzymuje żadnego stanu między połączeniami. Odpowiedź Ryana Cogswella również zawiera dobry przykład różnic.tldr
A
ref
to zwykły obiekt JS{ current: <some value> }
.React.createRef()
to fabryka zwracająca ref{ current: null }
- bez magii .
Jest to wystarczające do użyciauseRef(initValue)
zwraca również ref{ current: initValue }
pokrewny doReact.createRef()
. Poza tym zapamiętuje to odniesienie, aby było trwałe w wielu renderach w komponencie funkcji .React.createRef
w komponentach klas, ponieważ obiekt ref jest przypisany do zmiennej instancji , stąd jest dostępny w całym komponencie i jego cyklu życia:this.myRef = React.createRef(); // stores ref in "mutable" this context (class)
useRef(null)
w zasadzie jest równoważneuseState(React.createRef())[0]
1 .1 Wymienić
useRef
zuseState
+createRef
Poniższy tweet był dla mnie pouczający:
Dzięki spostrzeżeniom z
tldr
sekcji możemy teraz podsumować:Powyższy kod „nadużywa”,
useState
aby zachować zwrócony refReact.createRef()
.[0]
po prostu wybiera część wartościuseState
-[1]
będzie ustawiaczem.useState
powoduje ponowne renderowanie w przeciwieństwie douseRef
. Bardziej formalnie, React porównuje stare i nowe odniesienie do obiektuuseState
, gdy nowa wartość jest ustawiana za pomocą metody ustawiającej. Gdybyśmy mutować stanuuseState
bezpośrednio (w przeciwieństwie do setter pw), jego zachowanie staje się bardziej lub mniej równoważne douseRef
, a nie ponowne renderowanie jest wyzwalany już:// Example of mutaing object contained in useState directly const [ref] = useState({ current: null }) ref.current = 42; // doesn't cause re-render
Uwaga: nie rób tego! Skorzystaj ze zoptymalizowanego
useRef
API zamiast wymyślać koło na nowo. Powyższe ma charakter ilustracyjny.źródło
Żeby podkreślić cel:
createRef
jest tak proste, jakreturn {current: null}
. Jest to sposób na obsługęref=
rekwizytów w najnowocześniejszy sposób i to wszystko (podczas gdy oparte na ciągach znaków jest zbyt rozwlekłe).useRef
przechowuje niektóre dane przed renderowaniem, a ich zmiana nie powoduje ponownego renderowania (tak jak touseState
robi). Rzadko są spokrewnieni. Wszystko, czego oczekujesz od komponentu opartego na klasach, przechodzi do pól instancji (this.* =
) wygląda jak kandydat do zaimplementowaniauseRef
w komponentach funkcjonalnych.Say
useCallback
działa jak metody klasy ograniczonej (this.handleClick = .....bind(this)
) i może zostać ponownie zaimplementowane (ale na pewno nie powinniśmy ponownie wymyślać koła) zuseRef
.Innymi przykładami są odniesienia DOM, identyfikatory limitów czasu / interwałów, identyfikatory lub odwołania do bibliotek zewnętrznych.
PS Uważam, że zespół React lepiej wybrał inne nazewnictwo,
useRef
aby uniknąć nieporozumieńcreateRef
. MożeuseAndKeep
a nawetusePermanent
.źródło
Kolejny, ale ważny dodatek do odpowiedzi innych.
Nie możesz ustawić nowej wartości dla
createRef
. Ale możeszuseRef
.const ur = useRef(); const cr = createRef(); ur.current = 10; // you can do it, and value is set cr.current = 10; // you can, but it's no good, it will not change it
źródło
current
właściwość jak zwykle (właśnie to przetestowałem). Nie ma znaczenia, czy ref jest tworzony za pomocąuseRef
lubcreateRef
.