Saya sedang membaca dokumentasi hook ketika saya menemukan useRef
.
Melihat contoh mereka…
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>
</>
);
}
… Sepertinya useRef
bisa diganti dengan 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>
</>
);
}
Mengapa saya membutuhkan pengait untuk ref? Mengapa useRef
ada?
sumber
useRef
, yang diposting oleh salah satu pengembang React. Ini tidak sama dengan hanya meneleponcreateRef
, karenacreateRef
bukan hook dan tidak mempertahankan status apa pun di antara panggilan. Jawaban Ryan Cogswell juga memiliki contoh perbedaan yang bagus.tldr
A
ref
adalah objek JS biasa{ current: <some value> }
.React.createRef()
adalah pabrik yang mengembalikan wasit{ current: null }
- tidak melibatkan sihir .
Ini cukup untuk digunakanuseRef(initValue)
juga mengembalikan referensi yang{ current: initValue }
mirip denganReact.createRef()
. Selain itu, ia memoasi ref ini agar tetap ada di beberapa render dalam sebuah komponen fungsi .React.createRef
dalam komponen kelas, karena objek ref ditugaskan ke variabel instan , sehingga dapat diakses di seluruh komponen dan gaya hidupnya:this.myRef = React.createRef(); // stores ref in "mutable" this context (class)
useRef(null)
pada dasarnya setara denganuseState(React.createRef())[0]
1 .1 Gantikan
useRef
denganuseState
+createRef
Berikut tweet yang telah mencerahkan bagi saya:
Dengan wawasan dari
tldr
bagian tersebut, kita sekarang dapat menyimpulkan lebih lanjut:Di atas kode "penyalahgunaan"
useState
untuk mempertahankan ref yang dikembalikan dariReact.createRef()
.[0]
hanya memilih bagian nilaiuseState
-[1]
akan menjadi penyetel.useState
menyebabkan render ulang berbeda denganuseRef
. Secara lebih formal, React membandingkan referensi objek lama dan baruuseState
, ketika nilai baru ditetapkan melalui metode penyetelnya. Jika kita mengubah statususeState
secara langsung (berlawanan dengan pemanggilan setter), perilakunya kurang lebih menjadi sama denganuseRef
, karena tidak ada render ulang yang dipicu lagi:// Example of mutaing object contained in useState directly const [ref] = useState({ current: null }) ref.current = 42; // doesn't cause re-render
Catatan: Jangan lakukan ini! Gunakan
useRef
API yang dioptimalkan alih-alih menciptakan kembali roda. Di atas untuk tujuan ilustrasi.sumber
Hanya untuk menyoroti tujuan:
createRef
sesederhana itureturn {current: null}
. Ini adalah cara untuk menanganiref=
prop dengan cara paling modern dan hanya itu (sementara berbasis string terlalu ajaib dan berbasis panggilan balik terlihat terlalu verboose).useRef
menyimpan beberapa data sebelum merender dan mengubahnya tidak menyebabkan render ulang (sepertiuseState
halnya). Mereka jarang berhubungan. Semua yang Anda harapkan untuk komponen berbasis kelas masuk ke bidang contoh (this.* =
) terlihat seperti kandidat untuk diimplementasikanuseRef
dalam komponen fungsional.Katakanlah
useCallback
bekerja sebagai metode kelas terbatas (this.handleClick = .....bind(this)
) dan dapat diimplementasikan kembali (tetapi kita tidak harus menemukan kembali roda untuk yakin) denganuseRef
.Contoh lain adalah referensi DOM, ID waktu tunggu / interval, pengenal atau referensi perpustakaan pihak ketiga.
PS Saya yakin tim React lebih baik memilih penamaan yang berbeda untuk
useRef
menghindari kebingungancreateRef
. MungkinuseAndKeep
atau bahkanusePermanent
.sumber
Namun tambahan lain tapi penting untuk jawaban orang lain.
Anda tidak dapat menetapkan nilai baru untuk
createRef
. Tapi Anda bisa untukuseRef
.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
sumber
current
propertinya seperti biasa (baru saja mengujinya). Tidak masalah, jika ref dibuat melaluiuseRef
ataucreateRef
.