immer 和useImmer兩個庫有啥區別
immer
和 useImmer
是兩個緊密相關的庫,但它們在用途上有一定的區別:
immer:
immer
是一個 JavaScript 庫,專注於提供一種簡潔高效的不可變資料管理方式。它利用 Proxy 物件和 WeakMap 實現了所謂的“proxy-based immutability”,允許開發者以直觀的可變方式運算元據,而實際上並不會改變原始資料,而是建立一個全新的、經過更新的不可變物件。這樣既保證了資料的安全性(避免意外修改原始資料),又大大降低了編寫純函式式程式碼的複雜度。
import produce from 'immer';
let originalState = { users: [{ id: 1, name: 'Alice' }] };
let nextState = produce(originalState, draft => {
draft.users.push({ id: 2, name: 'Bob' });
});
useImmer:
useImmer
是一個基於 immer
庫實現的 React Hook。它專門為 React 應用程式設計,用於簡化狀態管理中的不可變資料更新。在React中,使用 useState
更新複雜的巢狀狀態通常較為繁瑣,而 useImmer
提供了一種簡便的方式來建立可變代理物件,透過這個代理物件修改狀態,React元件的狀態就會自動更新,並且始終保持不可變原則。
import React from 'react';
import { useImmer } from 'use-immer';
function UserList() {
const [users, updateUsers] = useImmer([{ id: 1, name: 'Alice' }]);
function addUser(newUser) {
updateUsers(draft => {
draft.push(newUser);
});
}
return (
// 渲染使用者列表...
<button onClick={() => addUser({ id: 2, name: 'Bob' })}>Add User</button>
);
}
總結:
immer
是底層庫,提供了通用的不可變資料更新機制。useImmer
是基於immer
構建的 React Hook,專為在React元件內部實現狀態管理時,以更符合直覺的方式進行不可變資料更新而設計。
那如果在react中直接使用immer該如何書寫?
在React中直接使用immer
進行狀態管理,你可以結合React的useState
或useReducer
Hook來實現。以下是一個使用useState
結合immer
的基本示例:
import React, { useState } from 'react';
import produce from 'immer';
function ExampleComponent() {
// 初始化狀態
const [state, setState] = useState({ users: [{ id: 1, name: 'Alice' }] });
// 使用immer更新狀態
function addUser(newUser) {
setState((prevState) =>
produce(prevState, (draft) => {
draft.users.push(newUser);
})
);
}
return (
<div>
{/* 渲染使用者列表 */}
{/* 新增使用者按鈕 */}
<button onClick={() => addUser({ id: 2, name: 'Bob' })}>Add User</button>
</div>
);
}
export default ExampleComponent;
在上述示例中,我們首先匯入了immer
庫的produce
函式,然後在元件內部定義了初始狀態並使用useState
進行管理。
當需要更新狀態時,我們不再直接修改狀態物件,而是透過produce
函式建立一個可變副本(draft),在draft上進行修改。
最後,immer會根據draft的修改情況返回一個新的狀態物件,從而實現狀態的不可變更新。
當然,如果你的應用程式有更復雜的狀態管理需求,也可以結合useReducer
Hook 使用immer來處理 reducer 中的狀態更新邏輯。