![translation](https://cdn.durumis.com/common/trans.png)
Ini adalah postingan yang diterjemahkan oleh AI.
Pilih Bahasa
Teks yang dirangkum oleh AI durumis
- Hook yang diawali dengan "use" yang sering digunakan di React bekerja dengan menyimpan nilai status dan melakukan re-rendering saat terjadi perubahan, menggunakan dispatcher dari objek global.
- useState merender ulang seluruh komponen, tetapi menggunakan virtual DOM untuk memodifikasi DOM yang berubah, dan meskipun dijalankan setiap re-rendering, ia mempertahankan nilai status melalui struktur daftar tertaut yang menggunakan variabel global.
- Saat re-rendering, fungsi-fungsi seperti updateState dan rerenderState dipanggil untuk memperbarui nilai status, dan bekerja dengan memanggil fungsi lain sesuai dengan peristiwa.
Anehnya, lingkungan React sangat menyukai penggunaan awalan 'use'.
useServer, useCallback, useState, useMemo, dan lain sebagainya.
Hook kustom pun juga menggunakan awalan 'use'.
Dari mana asalnya?
useState adalah hook yang terkenal.
Menyimpan nilai keadaan dan memicu render ulang saat nilai tersebut berubah. Sangat sederhana.
import { useState } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
return (
You clicked {count} times
);
Ini adalah contoh yang semua orang tahu.
Dikatakan bahwa render ulang terjadi saat nilai keadaan berubah, tetapi bagaimana ruang lingkup render ulang tersebut?
Hanya tag
? Atau sampai tag
Jawabannya adalah seluruh komponen tempat useState dipanggil.
ExampleComponent dirender ulang, tetapi
katanya menggunakan Virtual DOM untuk membandingkan nilai dan hanya mengubah DOM di tempat yang berbeda.
useState dipanggil pada setiap render ulang, bagaimana nilai keadaan tetap terjaga?
Jawabannya terletak pada struktur useState.
// react/packages/react/src/ReactHooks.js
export function useState(
initialState: (() => S) | S,
): [S, Dispatch] {
const dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
Ini adalah kode useState React yang sebenarnya.
Dispatcher diambil dari objek global dan menembakkan useState.
Struktur ini masih belum jelas.
Mari kita selami lebih dalam, kita akan menemukan kode berikut.
function mountState(
initialState: (() => S) | S,
): [S, Dispatch] {
const hook = mountStateImpl(initialState);
const queue = hook.queue;
const dispatch: Dispatch = (dispatchSetState.bind(
null,
currentlyRenderingFiber,
queue,
): any);
queue.dispatch = dispatch;
return [hook.memoizedState, dispatch];
Hook diambil dan fungsi set langsung dikaitkan dengan antrian yang ada di hook.
(Bind mengikat 'this' ke fungsi yang ada, menggunakan sisa nilai argumen sebagai argumen fungsi tersebut, kemudian mengembalikan fungsi baru dengan 'this' yang terikat.)
Ini masih sulit untuk dipahami alasannya.
Mari kita selami lebih dalam lagi.
function mountStateImpl(initialState: (() => S) | S): Hook {
const hook = mountWorkInProgressHook();
if (typeof initialState === 'function') {
const initialStateInitializer = initialState;
initialState = initialStateInitializer();
}
hook.memoizedState = hook.baseState = initialState;
const queue: UpdateQueue = {
pending: null,
lanes: NoLanes,
dispatch: null,
lastRenderedReducer: basicStateReducer,
lastRenderedState: (initialState: any),
};
hook.queue = queue;
return hook;
Kita dapat melihat bahwa nilai init diberikan pada setiap kali. Ini tidak menjelaskan mengapa keadaan tetap terjaga.
Mari kita selami lebih dalam lagi. Hook terlihat mencurigakan.
function mountWorkInProgressHook(): Hook {
const hook: Hook = {
memoizedState: null,
baseState: null,
baseQueue: null,
queue: null,
next: null,
};
if (workInProgressHook === null) {
// This is the first hook in the list
currentlyRenderingFiber.memoizedState = workInProgressHook = hook;
} else {
// Append to the end of the list
workInProgressHook = workInProgressHook.next = hook;
}
return workInProgressHook;
currentlyRenderingFiber dan workInProgressHook adalah variabel global.
Ini adalah bentuk implementasi linked list menggunakan alokasi dari kanan ke kiri.
Oleh karena itu, jika kita melihat hook, struktur yang diharapkan adalah sebagai berikut.
{
memoizedState: 0, // first hook
baseState: 0,
queue: { /* ... / },
baseUpdate: null,
next: { // second hook
memoizedState: false,
baseState: false,
queue: { / ... / },
baseUpdate: null,
next: { // third hook
memoizedState: {
tag: 192,
create: () => {},
destory: undefined,
deps: [0, false],
next: { / ... */ }
},
baseState: null,
queue: null,
baseUpdate: null,
next: null
}
}
Nilai di awal terus ditambahkan.
Penjelasannya masih belum jelas, setelah melihat implementasi useState lainnya
ternyata tidak semua implementasi memanggil mountState, tetapi memanggil updateState dan rerenderState saat render ulang.
Oleh karena itu, struktur tersebut adalah seperti yang ada di atas, dan fungsi lain dipanggil sesuai dengan event.
Jika Anda ingin melihat langsung kodenya, Anda dapat merujuk pada react/packages/react-reconciler/src/ReactFiberHooks.js.