Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Immer #194

Open
hysryt opened this issue Jan 10, 2022 · 3 comments
Open

Immer #194

hysryt opened this issue Jan 10, 2022 · 3 comments

Comments

@hysryt
Copy link
Owner

hysryt commented Jan 10, 2022

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

@hysryt
Copy link
Owner Author

hysryt commented Jan 10, 2022

イントロダクション

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

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

  • 想定外の変更を検出し、エラーを投げる
  • ディープアップデートに必要な冗長なコードの記述の削減
  • 専用のAPIを学ぶ必要なく、上記の恩恵を受けられる

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
Copy link
Owner Author

hysryt commented Jan 11, 2022

インストール

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
Copy link
Owner Author

hysryt commented Jan 16, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant