React 19 telah dikeluarkan pada 25 April 2024. Dunia JavaScript berubah dengan pantas sehingga kadangkala berasa sukar untuk mengikutinya. Tetapi apabila perubahan ini bertujuan untuk menjadikan hidup anda sebagai pembangun React lebih mudah, anda patut melihatnya, bukan? Memandangkan React merupakan bahagian penting dalam ekosistem ini, sentiasa dikemas kini adalah satu kemestian.
Bahagian terbaik tentang React 19 ialah ia memfokuskan untuk menjadikan perkara lebih mudah. Kemas kini direka untuk menjadikan pembelajaran React lebih mudah dan membolehkan anda meluangkan lebih banyak masa untuk membuat dan bukannya berurusan dengan persediaan yang rumit. Beberapa ciri baharu benar-benar mengubah permainan dan boleh membuat perubahan besar dalam cara anda bekerja, jadi anda pasti tidak mahu ketinggalan.
Saya sentiasa cuba menerangkan sesuatu dengan cara yang mudah difahami, tanpa melemparkan perkataan yang rumit. Artikel ini tidak terkecuali. Matlamat saya ialah untuk memastikan anda mendapat segala-galanya dengan jelas, jadi mari kita terokai kemas kini hebat dalam React 19 bersama-sama!
Ingat, React 19 belum lagi stabil. Pada masa ini ia dipanggil React Canary. Jadi, perlu diingat bahawa ia sebenarnya tidak disyorkan untuk pengeluaran.
Untuk mengoptimumkan aplikasi React kami, kami menggunakan beberapa kaedah terbina seperti useMemo, useCallback atau memo. Ini memberitahu React untuk tidak menyusun kod lagi jika input tidak berubah. Tetapi jika anda terlupa menggunakan penghafalan, ia mengakibatkan pembaziran sumber React dan kuasa pengiraan. Untuk menangani perkara ini, React 19 memperkenalkan React Compiler. Penyusun baharu React ialah bola mata keluaran baharu versi ke-19. Pengkompil baharu mengoptimumkan kod anda di sebalik tabir, jadi anda boleh melepaskan cangkuk ini dan menumpukan pada menulis komponen React yang cantik dan bersih.
Ringkasnya, anda tidak perlu membungkus fungsi anda dengan useMemo atau useCallback untuk prestasi yang dioptimumkan, dan anda juga tidak perlu membungkus komponen anda dengan memo untuk mengelakkan memaparkan semula komponen anda.
Mari kita bercakap kosong?!! Pernahkah anda perasan bagaimana cangkuk useTransition hampir tidak disebut sebelum React 19 keluar? Atau adakah hanya saya? Nah, sekurang-kurangnya itulah yang saya perhatikan, terutamanya dalam kalangan Pemaju Muda. Bagaimanapun, izinkan saya memberi anda idea tentang cara ia berfungsi dalam versi sebelumnya dan kemudian kita akan melihat mengapa ciri ini menjadi ciri penting sekarang.
useTransition mengembalikan tatasusunan dengan dua elemen, fungsi startTransition dan isPending boolean. Anda boleh membungkus kemas kini keadaan anda di dalam fungsi startTransition untuk menandakannya sebagai peralihan (kurang kod keutamaan). Ini bermakna bahagian yang dibalut dengan startTransition mula berfungsi selepas tugasan berterusan yang lain selesai.
Dalam React 18, fungsi startTransition tidak menyokong fungsi async secara langsung. Ini adalah had kerana startTransition direka bentuk untuk menandakan kemas kini sebagai keutamaan rendah tetapi tidak dapat mengendalikan logik tak segerak secara asli.
Dalam React 19, had ini telah ditangani. Sekarang, startTransition menyokong fungsi tak segerak, bermakna anda boleh melaksanakan tugas tak segerak di dalamnya (cth., pengambilan data) sambil memastikan kemas kini tersebut ditandakan sebagai peralihan. Penambahbaikan ini membolehkan penggunaan startTransition yang lebih fleksibel dan intuitif, menjadikannya seperti ciri "baharu" walaupun secara teknikalnya adalah penambahbaikan kepada yang sedia ada.
?
Mengikut konvensyen, fungsi yang menggunakan peralihan tak segerak dipanggil "Tindakan".
Sebagai contoh, anda boleh mengendalikan keadaan belum selesai dan ralat dalam useState:
// Before Actions function UpdateName({}) { const [name, setName] = useState(""); const [error, setError] = useState(null); const [isPending, setIsPending] = useState(false); const handleSubmit = async () => { setIsPending(true); const error = await updateName(name); setIsPending(false); if (error) { setError(error); return; } redirect("/path"); }; return ( <div> <input value={name} onChange={(event) => setName(event.target.value)} /> <button onClick={handleSubmit} disabled={isPending}> Update </button> {error && <p>{error}</p>} </div> ); }
React 19 menyokong menggunakan fungsi async dalam peralihan untuk mengendalikan keadaan belum selesai, ralat, borang dan kemas kini optimistik secara automatik. Sebagai contoh, anda boleh menggunakan useTransition untuk mengendalikan keadaan belum selesai untuk anda:
// Using pending state from Actions function UpdateName({}) { const [name, setName] = useState(""); const [error, setError] = useState(null); const [isPending, startTransition] = useTransition(); const handleSubmit = () => { startTransition(async () => { const error = await updateName(name); if (error) { setError(error); return; } redirect("/path"); }) }; return ( <div> <input value={name} onChange={(event) => setName(event.target.value)} /> <button onClick={handleSubmit} disabled={isPending}> Update </button> {error && <p>{error}</p>} </div> ); }
Peralihan async akan segera menetapkan keadaan isPending kepada benar, membuat permintaan async(s) dan menukar isPending kepada false selepas sebarang peralihan. Ini membolehkan anda memastikan UI semasa responsif dan interaktif semasa data berubah.
Pasukan React menambah sokongan untuk menghantar fungsi sebagai tindakan.
export default function App() { const [name, setName] = useState( () => JSON.parse(localStorage.getItem("name")) || "Anonymous user" ) async function formAction(formData){ try { const newName = await updateNameInDB(formData.get("name")) setName(newName) } } return ( <> <p className="username"> Current user: <span>{name}</span> </p> <form action={formAction}> <input type="text" name="name" required /> <button type="submit">Update</button> </form> </> ) }
Fungsi formAction (anda boleh menamakan apa sahaja) memberi anda data borang dalam parameternya. Setiap medan dilambangkan dengan atribut nama dan oleh itu anda perlu berhati-hati dalam menamakan input. parameter formData sebenarnya adalah objek API Web FormData asli. Anda boleh mengetahuinya di mdn web docs. Satu lagi perkara yang baik ialah anda tidak perlu menggunakan event.preventDefault() kerana ia dikendalikan oleh React.
Apabila Tindakan borang berjaya, React menetapkan semula borang secara automatik. Tetapi jika anda ingin menetapkan semula
?
React.useActionState sebelum ini dipanggil ReactDOM.useFormState dalam keluaran Canary, tetapi ia telah dinamakan semula dan tidak digunakan lagi useFormState.
useActionState menjejaki keadaan komponen, status belum selesai dan menyediakan fungsi tindakan yang dibungkus untuk digunakan dalam bentuk atau mana-mana tempat lain yang mungkin kita mahu lakukan mutasi.
Berikut ialah contoh untuk memecahkannya dengan lebih deskriptif:
import { useActionState } from "react" import { updateNameInDB } from "../api/user" export default function App() { const [user, formAction, isPending] = useActionState(insertName, { name: "John Doe", error: null }) async function insertName(prevState, formData){ try { const response = await updateNameInDB(formData.get("name")) return {name: response.name} }catch(error){ return {...prevState, error: error.error} } } return ( <> {user?.name && ( <p> <p>How this hook works is described with reference to the example:</p> <ol> <li><p>The first argument of the useActionState hook is the "Action" function, which is defined here as insertName.</p></li> <li><p>The second argument is the initial state, which is accessible through the first element of the result array. In this example, the initial state includes name and error, and the state is represented as user in the component.</p></li> <li><p>The insertName function returns the updated state. If the operation is successful, it updates the name property. If an error occurs, it updates the error property while preserving the rest of the previous state.</p></li> <li> <p>The result of the useActionState hook is an array with three elements:</p> <ul> <li>The current state (user): Reflects the latest state of the data.</li> <li>A dispatchable function (formAction): Triggers the action when called, as seen in the form element's action attribute.</li> <li>A pending state (isPending): Tracks whether the action is currently in progress, useful for managing transitions or loading indicators.</li> </ul> </li> </ol> <h2> New Hook: useOptimistic </h2> <p>When it’s performing a data mutation and to show the final state right after the user instructs (could be a tap on a button) or you could say optimistically while the async request is underway, you need to use this hook. Here is a demonstration how you can do this:<br> </p> <pre class="brush:php;toolbar:false">function ChangeName({currentName, onUpdateName}) { const [optimisticName, setOptimisticName] = useOptimistic(currentName); const submitAction = async (formData) => { const newName = formData.get("name"); setOptimisticName(newName); const updatedName = await updateName(newName); onUpdateName(updatedName); }; return ( <form action={submitAction}> <p>Your name is: {optimisticName}</p> <p> <label>Change Name:</label> <input type="text" name="name" disabled={currentName !== optimisticName} /> </p> </form> ); }
Kait useOptimistic akan segera memaparkan optimisticName semasa permintaan updateName sedang dijalankan. Apabila kemas kini selesai React akan memasukkan nilai yang dikemas kini dalam currentName atau jika kemas kini mendapat ralat, React akan bertukar semula secara automatik kepada nilai currentName.
useFormStatus hook membantu anda menjejaki penyerahan borang anda. Tunggu sebentar?! adakah ia satu lagi cangkuk untuk menjejaki peralihan async? baik jawapannya adalah 'ya' dan 'tidak' kedua-duanya. Memandangkan anda telah mempelajari cangkuk useActionState, anda boleh mengatakan ini adalah cangkuk lain untuk menjejak peralihan asinkron. Tetapi useFormStatus tidak menyebabkan sebarang tindakan berlaku, sebaliknya ia memberikan maklumat status penyerahan borang terakhir.
// Before Actions function UpdateName({}) { const [name, setName] = useState(""); const [error, setError] = useState(null); const [isPending, setIsPending] = useState(false); const handleSubmit = async () => { setIsPending(true); const error = await updateName(name); setIsPending(false); if (error) { setError(error); return; } redirect("/path"); }; return ( <div> <input value={name} onChange={(event) => setName(event.target.value)} /> <button onClick={handleSubmit} disabled={isPending}> Update </button> {error && <p>{error}</p>} </div> ); }
Nah, saya akan katakan perkara paling penting untuk diperhatikan di sini ialah useFormStatus hook sebenarnya berasal dari react-dom, bukan react.
useFormStatus membaca status