ys memos

Blog

recoilすき


react

2021/07/08


最近,自分の時間には React を使って開発することが多い.

1年前くらいに初めて触れてから,いくつかの簡単な Web アプリを作って Firebase を用いて公開したりしている.

その過程で,React Context API や React Redux を試してみたりしていた.

ちなみに,本ブログも React (Next.js)によって構築している(2021/07/08 現在).


Facebook が開発・公開してる OSS の一つで,react 開発者に簡潔なグローバルなステート管理を提供するライブラリである.

文法も非常に簡潔で,必要なところで必要な分だけ,変数へのアクセスを提供してくれるため,開発をスムーズに勧める助けとなる.

「必要なところに必要な分だけ」というのが個人的には気に入っていて,それについては後述する.


大体以下のような人におすすめ

  • react hooks を普段から使っている
  • ステート管理にどれを使うか悩んでいる
  • dispatch が複雑で困っている
  • グローバルなステート管理に問題を抱えている

ここでは,npx create-react-app my-app --template typescriptで初期化されたアプリに対し,簡単なカウンターアプリを作ってみる.


install_recoil
$ npm install recoil

RecoilRootという名称の理由は分からないが,よくある<***Provider>のようなもの.

特にこだわりがなければ,広い範囲を囲めるようにindex.tsxApp.tsxなどに組み込むのがよいと思っている.

以下のように書く.

index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { RecoilRoot } from 'recoil';

import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

個人的には,/src/store/countState.tsのようなパスで作ることをおすすめする.

中身は以下のようにする.好みによってexport defaultにしても良いと思う.

countState.ts
import { atom } from 'recoil';

export const countState = atom({
	key: "countState",
	default: 0,
})

useRecoilStateは,ステートの値の参照および更新を行うことができる.

Counter.tsx
import React from 'react';
import { useRecoilState } from 'recoil';

import { countState } from './store/countState';

const Counter:React.FC<{}> = () => {
	const [count, setCount] = useRecoilState<number>(countState);
	return (
		<>
			<button onClick={() => setCount(count + 1)}>increment</button>
			<span>{count}</span>
			<button onClick={() => setCount(count - 1)}>decrement</button>
		</>
	)
}

export default Counter;

App.tsx
import React from 'react';

import logo from './logo.svg';
import './App.css';
import Counter from './Counter';

const App:React.FC<{}> = () => {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Counter />
      </header>
    </div>
  );
}

export default App;

グローバルなステートに対し,各コンポーネントは,「値の参照だけ」や「値の更新だけ」を行いたい場合もある.

そんな時でも,recoil では容易に要望を満たせる.


useRecoilValueを使うと,値の参照だけをすることができる.

CounterViewer.tsx
import React from 'react';
import { useRecoilValue } from 'recoil';

import { countState } from './store/countState';

const CounterViewer:React.FC<{}> = () => {
	const count = useRecoilValue<number>(countState);
	return (
		<>
			<span>{count}</span>
		</>
	)
}

export default CounterViewer;

useSetRecoilStateを使うと,値の更新だけをすることができる.

ちなみに,以下の例では,setCount(4)のようにすると,countの値は4になる.

CounterIncrementer.tsx
import React from 'react';
import { useSetRecoilState } from 'recoil';

import { countState } from './store/countState';

const Counter:React.FC<{}> = () => {
	const setCount = useSetRecoilState<number>(countState);
	return (
		<>
			<button onClick={() => setCount(oldcount => oldcount + 1)}>increment</button>
		</>
	)
}

export default Counter;

まず第一に,importの段階で,どのステートを使うのか分かる.

次に,関数コンポーネントの最初に Hooks と一緒に宣言するuse***<T>(***State)の段階で,各ステートに対して,何を行うのかが分かる.具体的には,「値を参照するのか?」「値を更新するのか?」である.

最後に好みの問題だが,簡単な状態管理にdispatch()のアクションを都度用意する必要がなく,開発が加速する.


私は今後も recoil を使っていく.

また,現状はまだSelectorは使ったことがないが,きちんと使い方を知っておきたいなと思っている.


関連タグを探す