管理 React 應用程式中的狀態是建立動態和響應式使用者介面的重要組成部分。傳統上,開發人員依賴不可變的更新,這會產生經過必要修改的狀態的新副本。雖然此方法提供了可預測性並有助於調試,但它可能會帶來效能損失,特別是在處理大型或複雜的資料結構時。
本文介紹了兩種流行的用於處理狀態的 React 框架;反應突變和沈浸。儘管透過不同的方式,這兩個庫都促進了不變性。
Mutative 的實作與 Immer 非常相似,儘管更強大。 Mutative 比 Immer 和原生減速器更有效地處理資料。 根據 Mutative 團隊的說法,這種狀態管理解決方案使不可變更新變得更加容易。它比普通手工製作的減速機大約快兩到六倍,比 Immer 快 10 倍以上。
以下是 Mutative.js 的一些好處:
例如,假設有一個包含列表的狀態物件。我們打算將清單中的最後一項標記為已完成,然後新增項目:
const state = { list: [ { text: 'Learn JavaScript', done: true }, { text: 'Learn React', done: true }, { text: 'Learn Redux', done: false }, ], };
如果我們要使用常規的不可變資料更新,我們可以寫如下:
const nextState = { ...state, list: [ ...state.list.slice(0, 2), { ...state.list[2], done: true, }, { text: 'Learn Mutative', done: true }, ], };
但是在使用 Mutative 時,我們可以這樣寫:
import { create } from 'mutative'; const nextState = create(state, (draft) => { draft.list[2].done = true; draft.list.push({ text: 'Learn Mutative', done: true }); });
這就是Mutative的基本用途,它可以讓我們更輕鬆地實現不可變的更新。
Immer,在德語中的意思是“總是”,是一個小包,可以讓使用不可變狀態變得更加方便。榮獲 2019 年 JavaScript 開源獎「最具影響力貢獻」獎。
這些好處往往是透過確保您始終建立物件、陣列或映射的編輯副本而不是更改其任何屬性來實現的。這會使編寫程式碼變得非常困難,並且很容易無意中打破此類限制。透過解決這些問題,Immer 將幫助您堅持不可變資料方法。以下是 React Immer 的一些好處:
如果 Immer 偵測到無意的突變,它會報告錯誤。
Immer 消除了對不可變物件進行深度修改時所需的常規樣板程式碼的要求。如果沒有 Immer,則必須在各個層級手動複製物件。通常,透過進行大量...傳播操作。使用 Immer 時,會對草稿物件進行修改,草稿物件會記錄這些修改並建立適當的副本,而不更改原始物件。
Immer 並不要求您掌握某些 API 或資料結構即可從該範式中獲利。 Immer 可讓您存取純 JavaScript 資料結構以及眾所周知的可變 JavaScript API,同時保持安全。
以下是一個用於快速比較的簡單範例:
const baseState = [ { title: "Learn JavaScript", done: true }, { title: "Try Immer", done: false } ]
假設我們有先前的基本狀態,我們需要更新第二個待辦事項並新增第三個待辦事項。然而,我們不想改變原來的baseState並避免深度克隆(以維持第一個待辦事項)。
如果沒有 Immer,保持不變性需要我們複製狀態物件的每個受影響的層級。
const nextState = baseState.slice() // shallow clone the array nextState[1] = { // replace element 1... ...nextState[1], // with a shallow clone of element 1 done: true // ...combined with the desired update } //Since nextState was freshly cloned, using push is safe here, // but doing the same thing at any arbitrary time in the future would // violate the immutability principles and introduce a bug! nextState.push({title: "Tweet about it"})
Immer 簡化了這個過程。我們可以使用生成函數,該函數將我們希望開始的狀態作為其第一個參數,將一個稱為配方的函數作為其第二個參數,該函數將收到一個草稿,我們可以對其進行簡單的修改。一旦配方完成,突變就會被記錄並用於創建下一個狀態。 generate 將處理所有必要的複製,同時還透過凍結資料來保護資料免受未來無意的更改。
import {produce} from "immer" const nextState = produce(baseState, draft => { draft[1].done = true draft.push({title: "Tweet about it"}) })
您正在尋找帶有 React 的 Immer 嗎?歡迎您直接造訪React + Immer網站。
Mutative 和 Immer 都以概念上相似的方式實現不可變更新,但存在影響效能的關鍵實現差異。詳細介紹如下:
Secret Sauce: This speed advantage boils down to how each library creates the final immutable state object. Mutative employs a highly optimized algorithm that efficiently builds a new data structure reflecting the changes you made in the draft, prioritizing raw speed.
Immer's Overhead: Immer, on the other hand, utilizes a proxy object to track mutations on the draft state. This approach offers more flexibility but comes with an overhead that can significantly slow things down, particularly when dealing with large datasets. It's like adding an extra step in the process.
Auto-Freeze and the Tradeoff: Immer offers an optional feature called auto-freeze, which helps prevent accidental modifications to the original state. This is great for safety, but it comes at a performance cost. Disabling auto-freeze can bring Immer closer to Mutative's speed, but then you lose the safety net.
Both Mutative and Immer offer an intuitive way to write state updates that appear to mutate the state but ultimately result in immutable updates. However, there are some differences in syntax and potential for errors:
Syntax Mutative: Leverages familiar syntax that resembles traditional mutations. You write code as if you're directly modifying the state object.
Example:
const draft = createDraft(currentState); draft.todos.push({ text: 'Buy milk' }); const newState = commit(draft);
Immer Syntax: Requires using specific Immer functions like produce to wrap your update logic.
Example:
const newState = produce(currentState, draft => { draft.todos.push({ text: 'Buy milk' }); });
Draft escapes occur when you unintentionally modify the original state object instead of the draft copy in libraries like Mutative and Immer.
Mutative: While Mutative's syntax might feel familiar, there's a higher risk of accidentally modifying the original state object (draft escapes). This can happen if you forget to use the commit function to finalize the changes and create the new state. It requires stricter discipline to ensure all modifications go through the draft.
Immer: Immer's syntax explicitly forces you to work within the draft state using functions like produce. This reduces the chance of accidentally modifying the original state, making it inherently safer.
Ultimately, the best choice depends on your specific project requirements and team preferences. Consider trying both libraries on a small project to see which one feels more comfortable for your developers.
以上是比較 React Mutative 與 React Immer的詳細內容。更多資訊請關注PHP中文網其他相關文章!