なんとかなれ

ゆるふわWebエンジニアのブログ

Reactの状態管理ライブラリRecoilに入門しかける

仕事で使われていて、コピペしたらなんかデータが取れたという状態だったので少し入門する。

Recoil

概要はこちらRecoil 状態管理ライブラリはReduxとかReact公式のuseContextが使われることが多いらしいが、弊社プロダクトではRecoilが使われていた。 Reactを開発しているFacebook(Meta)が開発しているから、良さそう感ある。

公式のGetting Startedをなぞってみる。

https://recoiljs.org/docs/introduction/getting-started この辺り引用

RecoilRoot

Components that use recoil state need RecoilRoot to appear somewhere in the parent tree. A good place to put this is in your root component:

import React from 'react';
import {
  RecoilRoot,
  atom,
  selector,
  useRecoilState,
  useRecoilValue,
} from 'recoil';

function App() {
  return (
    <RecoilRoot>  // ここ
      <CharacterCounter />
    </RecoilRoot>
  );
}

recoilを使うために上の方の階層でRecoilRootタグで囲う必要があるとのこと。ルートコンポーネントとかがおすすめとのこと。

Atom

An atom represents a piece of state. Atoms can be read from and written to from any component. Components that read the value of an atom are implicitly subscribed to that atom, so any atom updates will result in a re-render of all components subscribed to that atom:

翻訳: アトムは状態の断片を表します。アトムは、どのコンポーネントからでも読み書きができる。アトムの値を読み取るコンポーネントは、暗黙のうちにそのアトムを購読しているので、アトムの更新は、そのアトムを購読しているすべてのコンポーネントの再レンダリングにつながります。  (?)

const textState = atom({
  key: 'textState', // unique ID (with respect to other atoms/selectors)
  default: '', // default value (aka initial value)
});

途中よくわからなくなったけど要は「アトムは、どのコンポーネントからでも読み書きができる」ってことで良さそう(便利)

仕事コードでは上記部分を別ファイルに切り出していた。

ネーミング例はsubCategories(状態名)Atom.ts等にしている。

この場合、ユニークなIDをkey: 'subCategoriesAtom', などにして何の状態を持った変数なのか分かりやすくする。

Components that need to read from and write to an atom should use useRecoilState() as shown below: 翻訳: アトムからの読み取りとアトムへの書き込みが必要なコンポーネントは、以下のようにuseRecoilState()を使用する必要があります。

function CharacterCounter() {
  return (
    <div>
      <TextInput />
      <CharacterCount />
    </div>
  );
}

function TextInput() {
  const [text, setText] = useRecoilState(textState); //大事なところ

  const onChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={onChange} />
      <br />
      Echo: {text}
    </div>
  );
}

const [text, setText] = useRecoilState(textState);

こんな感じでuseStateみたいに値をセットできるみたい。

Selector

selector represents a piece of derived state. Derived state is a transformation of state. You can think of derived state as the output of passing state to a pure function that modifies the given state in some way:

翻訳: セレクタは、派生した状態の一部を表します。派生状態とは、状態の変換のことです。派生状態は、与えられた状態を何らかの方法で変更する純粋な関数に状態を渡したときの出力と考えることができます。 (??)

const charCountState = selector({
  key: 'charCountState', // unique ID (with respect to other atoms/selectors)
  get: ({get}) => {
    const text = get(textState);

    return text.length;
  },
});

We can use the useRecoilValue() hook to read the value of charCountState:

訳文:useRecoilValue()フックを使って、charCountStateの値を読み取ることができるのです。

function CharacterCount() {
  const count = useRecoilValue(charCountState);

  return <>Character Count: {count}</>;
}

簡単まとめ

selectorで少しややこしくなってしまったが、useRecoilStateAtomにセットした変数をuseRecoilValueを使ってグローバルに呼び出せるということだけを覚えておけばかなり便利そうということで簡単に締めます。