6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React HooksAdvent Calendar 2019

Day 21

react-trackedを使ってreduxのような機能を作ってみる

Last updated at Posted at 2019-12-21

はじめに

多くの方が既にuseContextやuseReducerを使い、Reduxのようなprops-drillingを回避するようなHooksを作っています。そこで今回はreact-trackedを使いReduxが解決した機能の一つであるpropsdrilling回避を実現したいと思います。
react-trackedの利点については@daishiさんのreact-trackedの紹介という記事をご参照ください。

react-trackedを使ってみる

今回はカウンターアプリを作っていきたいと思います。

ファイル構成

今回のファイル構成は以下です。store.jsにglobalに置きたい変数、reducerを置きます。

src
 |-- index.js
 |-- App.js
 |-- store.js
 |-- Components
   |-- Counter.js
   |-- Display.js

store.jsに初期値を設定&Reducerを置き、Providerを定義する

今回はカウンターアプリなので、以下のように設定します。

src/store.js
import { useReducer } from "react";
import { createContainer } from "react-tracked";

const initialState = { count: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT_COUNT":
      return { ...state, count: state.count + 1 };
    case "DECREMENT_COUNT":
      return { ...state, count: state.count - 1 };
    default:
      throw new Error();
  }
};

const useValue = () => useReducer(reducer, initialState);

export const {
  Provider,
  useTrackedState,
  useUpdate: useDispatch
} = createContainer(useValue);

ProviderをApp.jsに適用し、変数、reducerにアクセスできるようにする

Providerでコンポーネント全体をラップします。各コンポーネントに関しては下で説明します。

src/App.js
import React from "react";
import Display from "./Components/Display";
import Counter from "./Components/Counter";
import { Provider } from "./store";

const App = () => {
  return (
    <Provider>
      <Display />
      <hr />
      <Counter />
    </Provider>
  );
};

export default App;

Count機能を作るCounterコンポーネントとCountの値表示機能を作るDisplayコンポーネントを作成。

今回の作ったコンポーネントはComponentsディレクトリにまとめておきます。
まずはCount機能

src/Components/Counter.js
import React from "react";
import { useDispatch } from "../store";

const Counter = () => {
  const dispatch = useDispatch();

  return (
    <div>
      <button onClick={() => dispatch({ type: "INCREMENT_COUNT" })}>
        Plus
      </button>
      <button onClick={() => dispatch({ type: "DECREMENT_COUNT" })}>
        Minus
      </button>
    </div>
  );
};

export default Counter;

次に値表示機能

src/Components/Display.js
import React from "react";
import { useTrackedState } from "../store";

const Display = () => {
  const state = useTrackedState();
  return <div>count : {state.count}</div>;
};

export default Display;

完成品

完成品についてはこのCodeSandboxのリンクから見ることができるので、動作を確認してみてください。

最後に

カウンターアプリだと結構簡単に作ることができましたが、正直これだけだとreact-truckedの「不要なrenderがパフォーマンス低下を引き起こすのを防ぐ」という面は紹介できなかったかなと思います。
詳細については上で紹介した@daishiさんのreact-trackedの紹介という記事やreact-trackedのチュートリアルを見るとよくわかると思います。

参考文献

今回カウンターアプリを作るにあたり以下の記事を参考にさせていただきました。ありがとうございました。

Reduxから Context API with Hooks へ

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?