React應用依賴狀態來追踪應用數據。狀態會隨著用戶交互而改變。當狀態改變時,我們需要更新用戶界面顯示的狀態,這通常使用React的setState
方法實現。
由於React的狀態是不可變的(不能直接修改),當狀態變得複雜時,更新狀態會變得非常棘手,難以理解和維護。
這就是Immer發揮作用的地方。本文將探討如何使用Immer簡化React狀態管理。 Immer使用“draft”(草稿)的概念,你可以把它理解為狀態的副本,而不是狀態本身。你可以想像Immer對狀態執行了複製操作,然後在一個安全的地方進行修改,而不會影響原始狀態。所有更新都在draft上進行,只有draft中發生改變的部分才會更新到實際狀態中。
例如,你的應用狀態如下:
this.state = { name: 'Kunle', age: 30, city: 'Lagos', country: 'Nigeria' }
如果用戶慶祝31歲生日,我們需要更新age
的值。使用Immer,會創建一個狀態副本(draft)。
想像一下,這個副本被交給一個信使,信使將副本交給Kunle。現在有兩個副本:當前狀態和交給Kunle的draft副本。 Kunle將draft中的age
修改為31。然後,信使將修改後的draft返回應用,應用比較兩個版本,只更新age
,因為這是draft中唯一改變的部分。
這種方式不會破壞不可變狀態的原則,因為當前狀態不會被直接修改。 Immer簡化了不可變狀態的管理。
實踐示例:交通燈
讓我們用Immer構建一個簡單的交通燈應用。
使用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
是Immer提供的默認函數。我們將其作為參數傳遞給setState
方法。 produce
函數接收一個函數,該函數接受draft
作為參數。在這個函數內部,我們可以修改draft
副本。
更簡潔的寫法:
const handleLight = (state) => { return produce(state, (draft) => { draft.red = 'black'; draft.yellow = 'black'; draft.green = 'green'; draft.next = 'red'; }); }; // 在組件中使用: handleGreenLight = () => { const nextState = handleLight(this.state); this.setState(nextState); };
我們把當前狀態和接受draft
作為參數的函數傳遞給produce
函數。
另一個例子:購物清單
如果你使用過React一段時間,你應該熟悉擴展運算符(spread operator)。使用Immer,特別是處理數組狀態時,你不需要使用擴展運算符。
讓我們創建一個購物清單應用來進一步說明這一點。
組件代碼:
class App extends React.Component { // ... (constructor and other methods) ... 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 method) ... }
添加新商品時,我們需要更新清單狀態。使用setState
和擴展運算符:
handleSubmit = (e) => { // ... this.setState({ list: [...this.state.list, newItem] }); };
如果需要更新多個狀態,使用擴展運算符會變得非常複雜。使用Immer,這變得非常簡單。
如果我們想在狀態更新後調用回調函數呢?例如,我們想計算清單中商品的總價。
handleSubmit = (e) => { // ... this.setState( produce(draft => { draft.list = draft.list.concat(newItem); }), () => { this.calculateAmount(this.state.list); } ); }; calculateAmount = (list) => { let total = 0; list.forEach(item => total = item.price); this.setState( produce(draft => { draft.totalAmount = total; }) ); };
回調函數在狀態更新後被調用,並且使用更新後的狀態。
Immer Hooks
use-immer
是一個hook,允許你在React應用中管理狀態。讓我們用一個簡單的計數器示例來演示:
import React from "react"; import {useImmer} from "use-immer"; const Counter = () => { const [count, updateCounter] = useImmer({ value: 0 }); function increment() { updateCounter(draft => { draft.value ; }); } return ( <div> <h1 id="Counter-count-value">Counter {count.value}</h1> <button onclick="{increment}">Increment</button> </div> ); }; export default Counter;
useImmer
類似於useState
。它返回狀態和一個更新函數。組件加載時,狀態值與傳遞給useImmer
的值相同。使用返回的更新函數,我們可以創建一個increment
函數來增加計數器的值。
Immer還提供了一個類似useReducer
的hook: useImmerReducer
。
總結
你可以開始在你的下一個項目中使用Immer,或者逐步將其應用到當前項目中。它簡化了React狀態管理。 代碼示例可以在GitHub上找到。 (請提供GitHub鏈接,如果存在的話)
以上是使用沉浸式的反應狀態管理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

對於Astro,我們可以在構建過程中生成大部分網站,但是有一小部分服務器端代碼可以使用Fuse.js之類的搜索功能來處理搜索功能。在此演示中,我們將使用保險絲搜索一組個人“書籤”


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

WebStorm Mac版
好用的JavaScript開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

SublimeText3 Linux新版
SublimeText3 Linux最新版