Bereaksi kait - menang atau kalah?

gambar


Dengan dirilisnya React 16.6.0 baru, HOOKS (PROPOSAL) muncul di dokumentasi. Mereka sekarang tersedia di react 17.0.0-alpha dan dibahas dalam RFC terbuka : React Hooks . Mari kita lihat apa itu dan mengapa dibutuhkan di bawah potongan.


Ya itu adalah RFC dan Anda dapat memengaruhi implementasi akhir yang membahas dengan para pembuat reaksi mengapa mereka memilih pendekatan ini atau itu.


Mari kita lihat seperti apa bentuk kait standar:


import { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } 

Cobalah untuk berpikir tentang kode ini, ini adalah penggoda dan pada akhir artikel Anda sudah mengerti apa artinya. Hal pertama yang harus Anda ketahui adalah bahwa ini tidak merusak kompatibilitas ke belakang dan mungkin mereka akan ditambahkan dalam 16.7 setelah mengumpulkan umpan balik dan saran di RFC.


Seperti yang orang-orang jamin, ini bukan rencana untuk memotong kelas dari reagen.


Juga, kait tidak menggantikan konsep reaksi saat ini, semuanya ada di tempat alat peraga / negara / konteks / referensi. Ini hanyalah cara lain untuk menggunakan kekuatan mereka.


Motivasi


Sekilas, Hooks memecahkan masalah yang tidak terhubung yang muncul dengan dukungan puluhan ribu komponen selama 5 tahun dari facebook.


Hal yang paling sulit adalah menggunakan kembali logika dalam komponen stateful, reaksi tidak memiliki cara untuk melampirkan perilaku yang dapat digunakan kembali ke komponen (misalnya, hubungkan ke repositori). Jika Anda bekerja dengan Bereaksi, Anda tahu konsep HOC (komponen orde tinggi) atau render props. Ini adalah pola yang cukup baik, tetapi kadang-kadang mereka digunakan secara berlebihan, mereka memerlukan restrukturisasi komponen sehingga mereka dapat digunakan, yang biasanya membuat kode lebih rumit. Perlu melihat aplikasi reaksi yang khas dan akan menjadi jelas apa yang dipertaruhkan.


gambar


Ini disebut neraka terbungkus - neraka pembungkus.


Aplikasi dari HOC saja normal dalam realitas saat ini, mereka menghubungkan komponen ke toko / tema / lokalisasi / custom hock, saya pikir semua orang tahu ini.


Menjadi jelas bahwa reaksi memerlukan mekanisme primitif lain untuk memisahkan logika.


Dengan menggunakan pengait, kita dapat mengekstrak status komponen sehingga dapat diuji dan digunakan kembali. Hook memungkinkan Anda untuk menggunakan kembali state logic tanpa mengubah hierarki komponen. Ini memfasilitasi pertukaran tautan antara banyak komponen atau keseluruhan sistem. Juga, komponen kelas terlihat sangat menakutkan, kami menggambarkan metode siklus hidup dari componentDidMount / shouldComponentUpdate / componentDidUpdate , keadaan komponen, membuat metode untuk bekerja dengan keadaan / sisi, mengikat metode untuk instance komponen, dan sehingga dapat terus dan terus. Biasanya, komponen seperti itu melampaui garis x, di mana x cukup sulit untuk dipahami.


Kait memungkinkan Anda melakukan hal yang sama dengan memecah logika antar komponen menjadi fungsi-fungsi kecil dan menggunakannya di dalam komponen.


Kelas sulit untuk orang dan untuk mobil


Dalam mengamati kelas facebook adalah hambatan besar ketika belajar Bereaksi. Anda perlu memahami cara kerjanya, dan tidak bekerja seperti pada bahasa pemrograman lain, Anda juga harus ingat tentang pengikatan acara yang mengikat. Tanpa kalimat sintaks yang stabil, kode tersebut terlihat sangat bertele-tele. Orang-orang memahami alat peraga / pola keadaan dan apa yang disebut aliran data top-down, tetapi kelasnya cukup sulit untuk dipahami.


Terutama jika tidak terbatas pada templat, belum lama ini orang-orang dari reaksi bereksperimen dengan tata letak komponen dengan Prepack dan melihat hasil yang menjanjikan, namun demikian, komponen kelas memungkinkan Anda untuk membuat pola buruk yang tidak diinginkan yang membuat optimisasi ini menghilang, kelas juga tidak bermigrasi dengan sangat baik ketika Kelas ulang panas membuatnya tidak bisa diandalkan. Pertama-tama, orang-orang ingin memberikan API yang mendukung semua optimasi dan berfungsi dengan baik dengan reboot panas.


Lihatlah kaitnya


Kait negara


Kode di bawah ini membuat paragraf dan tombol, dan jika kita klik tombol, nilai dalam paragraf akan bertambah.


 import { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } 

Dari sini kita dapat menyimpulkan bahwa kait ini bekerja sama dengan konsep seperti state .
Metode useState sedikit lebih terperinci mengambil satu argumen, ini adalah nilai default dan mengembalikan sebuah tuple di mana ada nilai itu sendiri dan metode untuk mengubahnya, tidak seperti setState, setCount tidak akan melakukan penggabungan nilai, tetapi hanya memperbaruinya. Kami juga dapat menggunakan beberapa pernyataan negara, misalnya:


 function ExampleWithManyStates() { // Declare multiple state variables! const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); // ... } 

Karenanya, kami membuat beberapa status sekaligus dan kami tidak perlu memikirkan cara menguraikannya. Dengan demikian, dapat dibedakan bahwa kait adalah fungsi yang memungkinkan Anda untuk "terhubung" ke chip komponen kelas, sama seperti kait tidak berfungsi di dalam kelas, ini penting untuk diingat.


Pengait efek


Seringkali dalam komponen kelas, kami membuat fungsi efek samping, misalnya, berlangganan acara atau membuat permintaan data, biasanya untuk ini kami menggunakan metode componentDidUpdate / componentDidUpdate


 import { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } 

Ketika kami memanggil useEffect kami memberi tahu reaksi untuk melakukan 'efek samping' setelah memperbarui perubahan di pohon DOM. Efek dinyatakan di dalam komponen, oleh karena itu mereka memiliki akses ke alat peraga / negara. Dan kita dapat membuatnya dengan cara yang persis sama seperti yang kita suka.


 function FriendStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); function handleStatusChange(status) { setIsOnline(status.isOnline); } // ... 

Segera perlu memperhatikan efek samping kedua di dalamnya, kami mengembalikan fungsi, kami melakukan ini untuk melakukan beberapa tindakan setelah komponen melakukan unmount, dalam api baru ini disebut efek dengan pembersihan. Efek lain dapat mengembalikan apa pun.


Aturan kait


Hooks hanyalah fungsi javascript, tetapi mereka hanya membutuhkan dua aturan:


  • Kait harus dilakukan di bagian paling atas dari hierarki fungsi (ini berarti Anda tidak boleh memanggil kait dalam kondisi dan loop, jika reaksi tidak dapat menjamin urutan pelaksanaan kait)
  • Kait panggilan hanya di Bereaksi fungsi atau komponen fungsional atau kait panggilan dari kait kustom (ini di bawah).
    Untuk mengikuti aturan ini, orang-orang dari tim reaksi membuat plugin linter yang akan menimbulkan kesalahan jika Anda memanggil hook di komponen kelas atau dalam loop dan kondisi.

Kait kustom


Pada saat yang sama, kami ingin menggunakan kembali logika komponen stateful, biasanya HOC atau render props pola digunakan untuk ini, tetapi mereka membuat volume tambahan dari aplikasi kami.
Sebagai contoh, kami menjelaskan fungsi berikut:


 import { useState, useEffect } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; } 

Menyadari kode ini, itu akan menjadi pengait kustom yang dapat kita panggil dalam berbagai komponen. Misalnya, seperti ini:


 function FriendStatus(props) { const isOnline = useFriendStatus(props.friend.id); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; } 

atau lebih


 function FriendListItem(props) { const isOnline = useFriendStatus(props.friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {props.friend.name} </li> ); } 

Bagaimanapun, kami menggunakan kembali status komponen, setiap panggilan ke fungsi useFriendStatus menciptakan keadaan terisolasi. Perlu juga dicatat bahwa awal dari fungsi ini dimulai dengan penggunaan kata, yang berarti bahwa itu adalah hook. Kami menyarankan Anda mengikuti format ini. Anda dapat menulis kait khusus untuk apa saja, animasi / langganan / pengatur waktu dan banyak lagi.


Ada beberapa kait lagi.


useContext


useContext memungkinkan Anda untuk menggunakan nilai pengembalian yang biasa alih-alih renderProps, konteks yang ingin kami ambil ke dalamnya dan itu akan mengembalikannya kepada kami, sehingga kami dapat menyingkirkan semua HOC yang meneruskan konteks ke alat peraga.


 function Example() { const locale = useContext(LocaleContext); const theme = useContext(ThemeContext); // ... } 

Dan sekarang kita bisa menggunakan objek konteks dalam nilai balik.


useCallback


 const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], ); 

Seberapa sering Anda harus membuat komponen kelas hanya untuk menyimpan referensi ke suatu metode? Ini tidak perlu dilakukan lagi, kita bisa menggunakan useCallback dan komponen kita tidak akan digambar ulang karena tautan baru ke onClick telah tiba.


gunakanMemo


Kami mengembalikan nilai memized, nilai memized berarti itu dihitung hanya ketika salah satu argumen telah berubah, kedua kalinya hal yang sama tidak akan dihitung.


 const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); 

Ya, di sini Anda harus menduplikasi nilai dalam array sehingga hook mengerti bahwa mereka tidak berubah.


useRef


useRef mengembalikan nilai yang dimutasi, di mana bidang .current akan diinisialisasi dengan argumen pertama, objek akan ada selama komponen ada.
Contoh paling umum ketika berfokus pada input


 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> </> ); } 

gunakanMeterativeMethods


useImperativeMethods mengkustomisasi nilai instance yang dilewatkan dari induk dan menggunakan ref secara langsung. Seperti biasa, tautan langsung harus dihindari dan forwardRef harus digunakan


 function FancyInput(props, ref) { const inputRef = useRef(); useImperativeMethods(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return <input ref={inputRef} ... />; } FancyInput = forwardRef(FancyInput); 

Dalam contoh ini, komponen yang FancyInput dapat memanggil fancyInputRef.current.focus() .


gunakanMutationEffect


useMutationEffect sangat mirip dengan useEffect kecuali bahwa itu dimulai secara sinkron pada tahap ketika reaksi mengubah nilai DOM sebelum komponen tetangga diperbarui, kait ini harus digunakan untuk melakukan mutasi DOM.
Lebih baik untuk memilih menggunakan Efek untuk mencegah pemblokiran perubahan visual.


useLayoutEffect


useLayoutEffect mirip dengan useEffect kecuali bahwa itu berjalan secara sinkron setelah semua pembaruan DOM dan rendering ulang secara sinkron. Pembaruan yang direncanakan di useLayoutEffect diterapkan secara serempak sebelum browser dapat menggambar elemen. Anda juga harus mencoba menggunakan efek useEffect standar agar tidak memblokir perubahan visual.


useReducer


useReducer adalah pengait untuk membuat peredam yang mengembalikan status dan kemampuan untuk mengirim perubahan:


 const [state, dispatch] = useReducer(reducer, initialState); 

Jika Anda memahami cara kerja Redux, maka Anda memahami cara kerja useReducer . Contoh yang sama dengan penghitung di atas hanya melalui useReducer :


 const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'reset': return initialState; case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; } } function Counter({initialCount}) { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count} <button onClick={() => dispatch({type: 'reset'})}> Reset </button> <button onClick={() => dispatch({type: 'increment'})}>+</button> <button onClick={() => dispatch({type: 'decrement'})}>-</button> </> ); } 

UseReducer juga membutuhkan 3 argumen, ini adalah action yang harus dijalankan ketika reducer diinisialisasi:


 const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'reset': return {count: action.payload}; case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; } } function Counter({initialCount}) { const [state, dispatch] = useReducer( reducer, initialState, {type: 'reset', payload: initialCount}, ); return ( <> Count: {state.count} <button onClick={() => dispatch({type: 'reset', payload: initialCount})}> Reset </button> <button onClick={() => dispatch({type: 'increment'})}>+</button> <button onClick={() => dispatch({type: 'decrement'})}>-</button> </> ); } 

Kami juga dapat membuat konteks dalam peredam ini dan menggunakannya melalui hook useContext menggunakannya di seluruh aplikasi, ini tetap untuk pekerjaan rumah.


Untuk meringkas


Hooks adalah pendekatan yang cukup kuat untuk menyelesaikan wrapper-hell dan menyelesaikan beberapa masalah, tetapi semuanya dapat digunakan dengan satu definisi transfer tautan . Sudah mulai tampak koleksi kait untuk digunakan atau koleksi ini . Anda dapat mempelajari lebih lanjut tentang pengait di dokumentasi .

Source: https://habr.com/ru/post/id428317/


All Articles