コンポーネントからStoreのStateを変更するまでの流れ


はじめに

前回、react-reduxについて自分なりに記事を書きました。しかし実際にコンポーネントとstoreを繋いでstateを変更するのはどういう流れになっているのかさらに深堀するために今回はコードベースで書いてみようと思いました。

コンポーネント作成

それでは、早速やっていきましょう。
今回はボタンをクリックするとダイアログが発生する処理を書きます。そのダイアログが発生する箇所をstoreに記載します。
まずはstoreを繋ぐコンポーネント用意します。
今回は、material-uiボタンを置くだけの簡単なコンポーネントを作成します。

myComponent.tsx
import React from 'react';
import * as patientList from '../../store/MyComponent';
import Fab from '@material-ui/core/Fab';
import AddIcon from '@material-ui/icons/Add';
import Button from '@material-ui/core/Button';
import AddCircleIcon from '@material-ui/icons/AddCircle';

return (
    <React.Fragment>
        <Fab
            color='primary'
            style={{
                position: 'fixed',
                zIndex: 3,
                right: '2em',
                bottom: '2em',
            }}
            onClick={onListClick}
        >
            <AddIcon />
        </Fab>
    </React.Fragment>
);
export default MyComponent;

これでブラウザの右下に以下のようなボタンが表示される

storeの作成

次に上記で作成したコンポーネントに接続するstoreを作成します
今回実装したコードを表示します。

myComponent.ts
import * as React from 'react';
import { Action, Reducer } from 'redux';
import { AppThunkAction } from '.';
import { push, RouterAction } from 'react-router-redux'

export interface MyComponentState {
    master: Master;
    test: string;
    userData: any;
};

interface ClearAll {
    type: 'MYCOMPONENT/CLEAR_ALL';
}

interface ListClick {
    type: 'MYCOMPONENT/LIST_CLICK';
}

export type KnownAction =
    ListClick
    | ClearAll;

const unloadedState: MyComponentState = {
    master: {
        word: ''
    },
    test: '',
    userData: {}
};

export interface IActionCreators {
    onClick: () => AppThunkAction<KnownAction>;
};

export type ActionCreators = IActionCreators;

function setInit() {
    return 'test';
}

export const actionCreators: ActionCreators = {
    onClick: () => (dispatch, getState) => {
        alert('onClick run');
    },
}

export const reducer = (state: MyComponentState, incomingAction: Action) => {
    const action = incomingAction as KnownAction;
    switch (action.type) {
        case 'MYCOMPONENT/LIST_CLICK': {
            return {
                ...state,
            }
        }
        case 'MYCOMPONENT/CLEAR_ALL': {
            return {
                ...unloadedState,
            }
        }
        default:
            const exhaustiveCheck: never = action;
    }
    return state || unloadedState;
};

今回は、ボタンをクリックすると、'onClick run'というアラートを表示させるのでまず初めにonClickというActionの型を定義しました。

export interface IActionCreators {
    onClick: () => AppThunkAction<KnownAction>;
};

次に、stateを変更するActionの中身を実装します。
onClickというAction Creatorの中に処理の内容を実装します。
今回追加する処理はボタンをクリックすると'onClick run'というアラートを表示させるだけなので以下のような処理を追加します。

onClick: () => (dispatch, getState) => {
        alert('onClick run');
    },

このままでは、Actionが発行されてもstateを変更できないので最後にReducerを以下ように定義します。

export const reducer = (state: MyComponentState, incomingAction: Action) => {
    const action = incomingAction as KnownAction;
    switch (action.type) {
        case 'MYCOMPONENT/LIST_CLICK': {
            return {
                ...state,
            }
        }
        case 'MYCOMPONENT/CLEAR_ALL': {
            return {
                ...unloadedState,
            }
        }
        default:
            const exhaustiveCheck: never = action;
    }
    return state || unloadedState;
};

これでstoreの実装は完成しました。
次に、このstoreをコンポーネントに接続する必要があります。

myComponent.tsx
export default MyComponent;

この箇所を以下のように修正してstoreに接続できるようにします。
connectを用いてstoreと接続します。

myComponent.tsx
export default connect(
  (state: ApplicationState) => (state.patientList),
  (dispatch) => bindActionCreators({ ...myComponent.actionCreators }, dispatch)
)(MyComponent);

それでは動作確認を行います。

小さくですが、画面上部に'onClick run'というアラートが表示されたのでコンポーネントとstoreが接続できたことを確認できました。

まとめ

コンポーネントとstoreの接続フローを最小単位のコードベースで説明しました。
今回は、ただアラートを表示させるだけの簡単な処理になりました、画面遷移やその他の処理でもこの方法で実装することができます。
この方法を取ることでstateの管理が楽になるのでこれからの開発でも使っていこうと思います!