Negara digunakan untuk mengatur pemantauan data dari Bereaksi aplikasi. Negara berubah saat pengguna berinteraksi dengan aplikasi. Ketika pengguna melakukan beberapa tindakan, kita perlu memperbarui keadaan, yang merupakan kumpulan data berdasarkan apa yang pengguna lihat di layar terbentuk. Perbarui keadaan Bereaksi aplikasi menggunakan metode
setState .

Karena negara tidak boleh diperbarui secara langsung (dalam Bereaksi, negara harus tidak berubah), dengan kerumitan struktur negara, bekerja dengan mereka berubah menjadi tugas yang sangat sepele. Yakni, menjadi sulit bagi programmer untuk bernavigasi di negara bagian dan menggunakan datanya dalam aplikasi.
Dalam situasi seperti itu, Anda dapat menggunakan perpustakaan Immer. Penggunaannya dalam React-aplikasi dikhususkan untuk materi, terjemahan yang kami terbitkan hari ini.
Dasar-dasar Penggunaan Immer dalam Aplikasi Bereaksi
Saat menggunakan Immer, struktur keadaan aplikasi Bereaksi dapat disederhanakan, yang berarti akan lebih mudah digunakan. Immer menggunakan konsep yang disebut "draft". "Draf" dapat diambil sebagai salinan negara, tetapi bukan negara itu sendiri.
Immer, seolah-olah, menyalin keadaan dengan "menekan" tombol CMD + C, kemudian, menggunakan kunci CMD + V, memasukkan apa yang disalin ke tempat di mana data yang disalin dapat dilihat tanpa mengganggu bahan aslinya. Mengubah data yang termasuk dalam negara bagian dilakukan dalam "konsep", setelah itu, berdasarkan perubahan yang dibuat pada "konsep", keadaan aplikasi saat ini diperbarui.
Misalkan kondisi aplikasi Anda terlihat seperti ini:
this.state = { name: 'Kunle', age: 30, city: 'Lagos', country: 'Nigeria' }
Ini adalah data pengguna. Pengguna ini, ternyata, sedang merayakan ulang tahunnya yang ke-31. Ini berarti bahwa kita perlu memperbarui umurnya (properti
age
). Jika Anda menggunakan Immer untuk menyelesaikan masalah ini, salinan dari status ini akan dibuat terlebih dahulu.
Sekarang bayangkan sebuah salinan kekayaan dibuat, itu diserahkan kepada kurir, dan dia mengirimkan salinan ini kepada Kunle. Ini berarti bahwa sekarang ada dua salinan negara. Salah satunya adalah keadaan aplikasi saat ini, dan yang kedua adalah salinan "kasar" yang ditransfer ke pengguna. Pengguna, mengedit "draft", mengubah usianya menjadi 31. Setelah itu, kurir kembali dengan dokumen yang diubah dan memberikan "draft" ke aplikasi. Di sana, perbandingan dua versi dokumen dilakukan, dan hanya perubahan yang berkaitan dengan usia pengguna yang dibuat dengan keadaan aplikasi saat ini, karena tidak ada lagi yang berubah dalam "konsep".
Skema kerja semacam itu tidak melanggar gagasan kekebalan negara - keadaan saat ini tidak diperbarui secara langsung. Secara umum, kita dapat mengatakan bahwa penggunaan Immer hanya membantu meningkatkan kegunaan keadaan kekebalan tubuh.
Contoh No. 1: lampu lalu lintas
Mari kita lihat contoh aplikasi yang menggunakan Immer. Misalkan Anda sedang mengembangkan aplikasi lampu lalu lintas. Dalam aplikasi ini Anda dapat mencoba menggunakan Immer.
Berikut tampilan layar aplikasi ini di salah satu momen operasinya.
Aplikasi lampu lalu lintasDi sini Anda dapat menemukan kode proyek.
Di sini akan terlihat seperti apa komponennya, mengingat bahwa proyek tersebut menggunakan Immer.
const {produce} = immer class App extends React.Component { state = { red: 'red', yellow: 'black', green: 'black', next: "yellow" } componentDidMount() { this.interval = setInterval(() => this.changeHandle(), 3000); } componentWillUnmount() { clearInterval(this.interval); } handleRedLight = () => { this.setState( produce(draft => { draft.red = 'red'; draft.yellow = 'black'; draft.green = 'black'; draft.next = 'yellow' }) ) } handleYellowLight = () => { this.setState( produce(draft => { draft.red = 'black'; draft.yellow = 'yellow'; draft.green = 'black'; draft.next = 'green' }) ) } handleGreenLight = () => { this.setState( produce(draft => { draft.red = 'black'; draft.yellow = 'black'; draft.green = 'green'; draft.next = 'red' }) ) } changeHandle = () => { if (this.state.next === 'yellow') { this.handleYellowLight() } else if (this.state.next === 'green') { this.handleGreenLight() } else { this.handleRedLight() } } render() { return ( <div className="box"> <div className="circle" style={{backgroundColor: this.state.red}}></div> <div className="circle" style={{backgroundColor: this.state.yellow}}></div> <div className="circle" style={{backgroundColor: this.state.green}}></div> </div> ); } };
Produce
adalah fitur standar yang diimpor dari Immer. Kami meneruskannya, sebagai nilai, ke metode
setState()
. Fungsi
produce
mengambil fungsi yang, sebagai argumen, mengambil
draft
. Dalam fungsi ini kita dapat mengedit status "draft", membawanya ke bentuk yang seharusnya berbentuk nyata.
Jika semua ini tampaknya terlalu rumit bagi Anda - berikut adalah pendekatan lain untuk menulis kode yang menyelesaikan tugas yang sama dengan kode di atas. Pertama, buat fungsi:
const handleLight = (state) => { return produce(state, (draft) => { draft.red = 'black'; draft.yellow = 'black'; draft.green = 'green'; draft.next = 'red' }); }
Untuk fungsi
produce
, kami, sebagai argumen, melewati status aplikasi saat ini dan fungsi lain yang menggunakan
draft
argumen. Sekarang mari kita manfaatkan semua ini dalam komponen:
handleGreenLight = () => { const nextState = handleLight(this.state) this.setState(nextState) }
Contoh 2: daftar belanja
Jika Anda telah bekerja dengan Bereaksi selama beberapa waktu, maka Anda seharusnya tidak terkejut dengan
sintaksis penyebaran . Saat menggunakan Immer, Anda tidak perlu menggunakan desain serupa. Secara khusus, ketika bekerja dengan array yang terdapat dalam keadaan.
Kami akan terus mengeksplorasi kemungkinan Immer, membuat aplikasi yang mengimplementasikan daftar belanja.
Daftar belanjaDi sini Anda dapat bereksperimen dengannya.
Berikut adalah komponen yang kami kerjakan.
class App extends React.Component { constructor(props) { super(props) this.state = { item: "", price: 0, list: [ { id: 1, name: "Cereals", price: 12 }, { id: 2, name: "Rice", price: 10 } ] } } handleInputChange = e => { this.setState( produce(draft => { draft[event.target.name] = event.target.value })) } handleSubmit = (e) => { e.preventDefault() const newItem = { id: uuid.v4(), name: this.state.name, price: this.state.price } this.setState( produce(draft => { draft.list = draft.list.concat(newItem) }) ) }; render() { return ( <React.Fragment> <section className="section"> <div className="box"> <form onSubmit={this.handleSubmit}> <h2>Create your shopping list</h2> <div> <input type="text" placeholder="Item's Name" onChange={this.handleInputChange} name="name" className="input" /> </div> <div> <input type="number" placeholder="Item's Price" onChange={this.handleInputChange} name="price" className="input" /> </div> <button className="button is-grey">Submit</button> </form> </div> <div className="box"> { this.state.list.length ? ( this.state.list.map(item => ( <ul> <li key={item.id}> <p>{item.name}</p> <p>${item.price}</p> </li> <hr /> </ul> )) ) : <p>Your list is empty</p> } </div> </section> </React.Fragment> ) } } ReactDOM.render( <App />, document.getElementById('root') );
Saat menambahkan catatan belanja baru ke daftar, kita perlu memperbarui keadaan komponen di mana, dalam array
list
, elemen baru harus disimpan. Untuk memperbarui item
list
menggunakan metode
setState()
,
setState()
memerlukan kode berikut:
handleSubmit = (e) => { e.preventDefault() const newItem = { id: uuid.v4(), name: this.state.name, price: this.state.price } this.setState({ list: [...this.state.list, newItem] }) };
Jika selama pengoperasian aplikasi Anda perlu memperbarui banyak elemen state - sintaks penyebaran harus sering digunakan. Status baru diperoleh dengan menggabungkan apa yang sudah ada dalam status dengan data baru. Ketika jumlah perubahan bertambah, pekerjaan menjadi lebih rumit. Jika menggunakan Immer - hal-hal seperti itu tidak menyebabkan kesulitan. Anda dapat memverifikasi ini dengan melihat kode contoh di awal bagian ini.
Tetapi bagaimana jika kita ingin menambahkan fungsi ke proyek itu, dalam bentuk panggilan balik, akan dipanggil setelah memperbarui negara? Misalnya, ini mungkin diperlukan jika Anda perlu menghitung jumlah entri dalam daftar atau total biaya semua pembelian yang direncanakan.
Di sini Anda dapat melihat kode aplikasi, yang sekarang akan kami analisis. Antarmukanya ditunjukkan di bawah ini.
Aplikasi dengan fungsi menghitung total biaya pembelian yang direncanakanJadi, anggaplah kita ingin menghitung nilai total pembelian yang direncanakan. Mari kita mulai dengan membuat mekanisme pembaruan status. Mekanisme ini diwakili oleh fungsi
handleSubmit
:
handleSubmit = (e) => { e.preventDefault() const newItem = { id: uuid.v4(), name: this.state.name, price: this.state.price } this.setState( produce(draft => { draft.list = draft.list.concat(newItem) }), () => { this.calculateAmount(this.state.list) } ) };
Dalam fungsi
handleSubmit
pertama-tama kita membuat objek berdasarkan data yang dimasukkan oleh pengguna. Referensi ke objek ditulis ke
newItem
konstan. Untuk membentuk keadaan baru aplikasi, metode
.concat()
digunakan. Metode ini, dipanggil pada array, mengembalikan array baru, yang mencakup elemen array asli, serta elemen baru. Array baru ditulis ke
draft.list
. Setelah itu, Immer dapat memperbarui status aplikasi.
Callback, fungsi
calculateAmount
, dipanggil setelah pembaruan keadaan. Penting untuk dicatat bahwa fungsi ini menggunakan versi negara yang diperbarui.
Fungsi
calculateAmount
akan terlihat seperti ini:
calculateAmount = (list) => { let total = 0; for (let i = 0; i < list.length; i++) { total += parseInt(list[i].price, 10) } this.setState( produce(draft => { draft.totalAmount = total }) ) }
Kait lebih dekat
Use-immer adalah pengait yang memungkinkan pengembang mengontrol keadaan aplikasi Bereaksi. Mari kita lihat bagaimana kait ini bekerja dengan mengimplementasikan aplikasi penghitung klasik berdasarkan:
import React from "react"; import {useImmer} from "use-immer"; const Counter = () => { const [count, updateCounter] = useImmer({ value: 0 }); function increment() { updateCounter(draft => { draft.value = draft.value +1; }); } return ( <div> <h1> Counter {count.value} </h1> <br /> <button onClick={increment}>Increment</button> </div> ); } export default Counter;
Fungsi
useImmer
sangat mirip dengan metode
useState . Fungsi mengembalikan status dan fungsi yang memperbarui status. Saat komponen dimuat pertama kali, konten negara (dalam hal ini, properti
count
) sesuai dengan nilai yang diteruskan ke
useImmer
. Menggunakan fungsi yang dikembalikan untuk memperbarui status memungkinkan kami untuk membuat fungsi kenaikan yang menambah nilai properti status
count
.
Dan di sini adalah kode yang menggunakan hook untuk Immer, mengingatkan kita pada
useReducer :
import React, { useRef } from "react"; import {useImmerReducer } from "use-immer"; import uuidv4 from "uuid/v4" const initialState = []; const reducer = (draft, action) => { switch (action.type) { case "ADD_ITEM": draft.push(action.item); return; case "CLEAR_LIST": return initialState; default: return draft; } } const Todo = () => { const inputEl = useRef(null); const [state, dispatch] = useImmerReducer(reducer, initialState); const handleSubmit = (e) => { e.preventDefault() const newItem = { id: uuidv4(), text: inputEl.current.value }; dispatch({ type: "ADD_ITEM", item: newItem }); inputEl.current.value = ""; inputEl.current.focus(); } const handleClear = () => { dispatch({ type: 'CLEAR_LIST' }) } return ( <div className='App'> <header className='App-header'> <ul> {state.map(todo => { return <li key={todo.id}>{todo.text}</li>; })} </ul> <form onSubmit={handleSubmit}> <input type='text' ref={inputEl} /> <button type='submit' > Add Todo </button> </form> <button onClick={handleClear} > Clear Todos </button> </header> </div> ); } export default Todo;
Fungsi
useImmerReducer
menerima fungsi
useImmerReducer
dan status awal. Ini mengembalikan fungsi negara dan
dispatch
. Setelah itu, Anda dapat melewati negara untuk menampilkan elemen di dalamnya. Tindakan pengiriman menggunakan fungsi
dispatch
dilakukan ketika item baru ditambahkan ke daftar tugas dan ketika daftar dihapus. Tindakan yang akan dikirim ditetapkan jenis berdasarkan keputusan yang dibuat dalam fungsi peredam tentang apa yang sebenarnya perlu dilakukan untuk memproses tindakan tertentu.
Dalam peredam, kami menggunakan, seperti sebelumnya, entitas
draft
, bukan
state
. Berkat ini, kami memiliki cara mudah untuk mengontrol status aplikasi.
Kode yang digunakan dalam contoh sebelumnya dapat ditemukan di
sini .
Ringkasan
Pada artikel ini, kita berbicara tentang Immer, perpustakaan yang menyederhanakan pengelolaan keadaan aplikasi Bereaksi. Penulis artikel percaya bahwa setiap orang yang tertarik pada perpustakaan ini dapat menggunakan Immer dalam aplikasi baru mereka atau secara perlahan memperkenalkannya ke dalam salah satu proyek saat ini.
Berikut adalah bahan di mana Anda dapat menemukan beberapa detail tentang Immer.
Pembaca yang budiman! Apakah Anda berencana menggunakan Immer?
