React Mutative と React Immer の比較

PHPz
PHPzオリジナル
2024-08-25 06:31:32613ブラウズ

Comparing React Mutative vs. React Immer

React アプリの状態管理は、動的で応答性の高いユーザー インターフェイスを作成する上で重要な部分です。従来、開発者は、必要な変更を加えた状態の新しいコピーを生成する不変の更新に依存していました。この方法は予測可能性を提供し、デバッグを容易にしますが、特に大規模または複雑なデータ構造を扱う場合、パフォーマンスが低下する可能性があります。

この記事では、状態を処理するための 2 つの一般的な React フレームワークについて説明します。 React Mutative と Immer。どちらのライブラリも、異なる手段を通じてではありますが、不変性を促進します。

React Mutative の概要

Mutative の実装は Immer の実装と非常に似ていますが、より堅牢です。 Mutative は、Immer やネイティブ Reducer よりも効率的にデータを処理します。 Mutative チームによると、この状態管理ソリューションにより、不変の更新が容易になります。これは、平均的な手作り減速機よりも約 2 ~ 6 倍高速であり、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 の基本的な使用法であり、不変の更新をより簡単に実装できるようになります。

React Immer の概要

ドイツ語で「常に」を意味する Immer は、不変状態の操作をより便利にする小さなパッケージです。 2019 JavaScript オープンソース賞「最も影響力のある貢献」を受賞。

React Immer の利点

これらの利点は、オブジェクト、配列、またはマップのプロパティを変更するのではなく、常に編集済みのコピーを作成することによって得られる傾向があります。これにより、コードの作成が非常に困難になる可能性があり、そのような制限を意図せずに破ってしまう可能性があります。これらの問題の解決を通じて、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
    }
]

前の基本状態があり、2 番目の ToDo を更新して 3 番目の ToDo を追加する必要があると仮定します。ただし、元の BaseState を変更したくなく、(最初の ToDo を維持するため) 深いクローン作成を避けます。

イマーなし

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 はこのプロセスを簡素化します。生成関数を使用できます。この関数は、最初の引数として開始したい状態を受け取り、2 番目のパラメーターとしてレシピと呼ばれる関数を受け取ります。この関数には、簡単な変更を適用できるドラフトが渡されます。レシピが完了すると、突然変異が記録され、次の状態を作成するために使用されます。 generate は、必要なコピーをすべて処理しながら、データを凍結することで将来の意図しない変更からデータを保護します。

import {produce} from "immer"

const nextState = produce(baseState, draft => {
    draft[1].done = true
    draft.push({title: "Tweet about it"})
})

React を備えた Immer をお探しですか? React + Immer の Web サイトに直接アクセスしてください。

コア機能

Mutative と Immer はどちらも概念的には同様の方法で不変の更新を実現しますが、パフォーマンスに影響する重要な実装の違いがあります。内訳は次のとおりです:

  1. Draft State: Both libraries create a draft version of the original state object. This draft behaves mostly like the original state, allowing you to write updates as if you were mutating it directly.
  2. Immutability Behind the Scenes: When you make changes to the draft state, these libraries aren't modifying the original object. Instead, they track the changes you make.
  3. Generating a New State: Once you're done with your updates in the draft state, Mutative, and Immer use different approaches to create a new, immutable state object reflecting the changes:
  4. Mutative: It leverages a high-performance algorithm to efficiently create a new data structure with the modifications from the draft. This approach prioritizes speed.
  5. Immer: It employs a proxy object that intercepts mutations on the draft and uses that information to construct a completely new, immutable state object. This approach offers more flexibility but can have some performance overhead. ## Performance Comparison When it comes to raw performance, Mutative reigns supreme over Immer, especially for updates involving large data structures. Here's why:
  6. Speed Demon: Benchmarks show Mutative can be a staggering 2-6 times faster than writing state updates with traditional reducers and a whopping over 10 times faster than Immer in its default settings.
  • 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.

    The Ease of Use Comparison

    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

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.

Conclusion

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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。