hysryt / wiki

https://hysryt.github.io/wiki/
0 stars 0 forks source link

Immer #194

Open hysryt opened 2 years ago

hysryt commented 2 years ago

https://immerjs.github.io/immer/ Immerはドイツ語で「常に」。 イミュータブルな状態を便利に扱うためのライブラリ。

hysryt commented 2 years ago

イントロダクション

イミュータブル(不変)なオブジェクトは効率的な変更検出を可能にする。 イミュータブルなオブジェクトであれば、オブジェクトへの参照が同じということはオブジェクトが同等であることを意味する。 さらに、クローン時には変更されていない箇所を共有することでコピーの処理を安価にする。

Immer によって以下のことが可能になる。

const baseState = [
    {
        title: "Learn TypeScript",
        done: true
    },
    {
        title: "Try Immer",
        done: false
    }
]

上記のオブジェクトを元に、新しいオブジェクトを追加し、1つ目のオブジェクトのdoneをfalseにしたい。 ただし、baseStateには手を加えず、新しいオブジェクトを作成する。

import produce from "immer"

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

produce は必要なコピーを全て行い、第二引数の関数にdraftとして渡す。

hysryt commented 2 years ago

インストール

npm install immer

CDN

<script src="https://unpkg.com/immer"></script>

サンプル

import { produce } from "immer";

const state = {
  count: 0,
};

const newState = produce(state, draft => {
  draft.count++;
});

console.log(newState);
$ node script.mjs
{ count: 1 }
hysryt commented 2 years ago

produce関数

produce(currentState, recipe: (draftState) => void): nextState

引数としてベースとなるステートと、ステートに対する変更を行う関数(immerではレシピと呼ぶ)を渡す。 ベースとなるステートはそのまま保たれる。 変更を加えた結果は戻り値として取得できる。

レシピの中では代入など全ての操作が可能。

curried producer

produceの第一引数に関数(レシピ)を与えると、与えられた状態に対して常に同じ変更を与える関数(producerと呼ぶ)を生成できる。 レシピはdraft以外の引数を取ることができる。 この引数はproducerの引数として渡す。

produce(fn): producer
const incrementer = produce((draft) => {
  draft.counter++
});

const state =  {
  counter: 0,
};

const next = incrementer(state);
const nextnext = incrementer(next);

console.log(nextnext.counter); // 2