immer 和useImmer兩個庫有啥區別

龙陌發表於2024-03-24

immer 和useImmer兩個庫有啥區別

immeruseImmer 是兩個緊密相關的庫,但它們在用途上有一定的區別:

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的useStateuseReducerHook來實現。以下是一個使用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 中的狀態更新邏輯。

相關文章