Reduxをざっくり理解する


Reactを使う上で切っても切れないのがReduxによる状態管理。
頑張って覚えるぞい。

読んだ記事

基本をおさえる

そもそもReduxってなんなの?状態だったので記事を漁る。
この辺でまず前提の知識は備わった。

最新のReduxを学ぶ

前回の記事でReact hooksを覚えたので、それに絡めたReduxの使い方をお勉強。

なるほど、わからん

読んだだけではちゃんとわからん。
個人的な解釈を整理する。

1.Actionを作る

Storeに対してやりたいことを書いておく。
typeは必須。あとで使う。
値を流す場合は受け渡しの処理を書く。

// Action
export const setComment = (comment) => 
 ({
    type: 'setComment',
    comment
  });

2. Reducerを作る

Actionの受け口で、Storeへのアクセスを管理する。
Actionで設定したtypeに対応した処理を書く。

// Reducer
export const reducer = (state = {comment: null}, action) => {
  switch (action.type) {
    case 'setComment': {
      console.log(action);
      return { ...state, comment: action.comment };
    }
    default: {
      return state;
    }
  }
}

3. Storeを作る

データを保持しておくところ。
メモリー常にFirebaseみたいなのを作るイメージ。
値を変更する時は必ずActionを通す。

// Store
export default createStore(combineReducers({foo :reducer}));

以上を踏まえたファイルがこちら。

redux.js
import { createStore, combineReducers } from 'redux';
import { useSelector, useDispatch } from 'react-redux';

// Action
export const setComment = (comment) => 
 ({
    type: 'setComment',
    comment
  });

// Reducer
export const reducer = (state = {comment: null}, action) => {
  switch (action.type) {
    case 'setComment': {
      console.log(action);
      return { ...state, comment: action.comment };
    }
    default: {
      return state;
    }
  }
}

// Store
export default createStore(combineReducers({foo :reducer}));

4. Storeに値を入れる

ではいよいよ使っていきます。
さっきも言ったようにStoreにデータを投入するときはAction->Reducerを経由しなければならない。
具体的にどうするかというと、ActionをDispatchする。

export const CommentForm = () => {
  const ref = useRef();
  const dispatch = useDispatch();

  return (
    <div>
      <input ref={ref} type="text" />
      <button onClick={() => dispatch(setComment(ref.current.value))}>comment</button>
    </div>
  );
}

ReduxにもHooks APIがあり、それを使うことで簡単に書けた。

(2019/09/06 追記)
子コンポーネントにdispatchさせる時はuseCallbackを使ってコールバック関数の参照が変わらないようにする。

export const CommentForm = () => {
  const ref = useRef();
  const dispatch = useDispatch();
  const setCommenter = useCallback(
    () => dispatch(setComment(ref.current.value)),
    [dispatch]
  )

  return (
    <div>
      <input ref={ref} type="text" />
      <CommentButton onSetComment={setCommenter} />
    </div>
  );
}

export const CommentButton = React.memo(({ onSetComment }) => (
  <button onClick={onSetComment}>comment</button>  
))

5. Storeから値を取得

こちらもHooks APIを使う。

export const Comment = () => {
  const comment = useSelector(state => state.foo.comment);
  return (
    <div>{comment}</div>
  );
}

stateの次に来るプロパティのキーはStore作成時に設定できる。
ES6ならそのまま入れれば変数名がキーになる。

// Store
export default createStore(combineReducers({reducer}));
export const Comment = () => {
  const comment = useSelector(state => state.reducer.comment);
  return (
    <div>{comment}</div>
  );
}

サンプルコード

前回hooksを試したやつを改造したサンプルコードがこちら


だいたい分かった。