action / reducer / store / index / App

React

src/reducks/users/actions.js

export const SIGN_IN = "SIGN_IN";
export const signInAction = (userState) => {
    return {
        type: "SIGN_IN",   <--- 依頼の種類
        payload: {
            isSignedIn: true,  <--- ユーザーがサインインしているかどうか
            uid: userState.uid,  <--- ユーザーのID
            username: userState.username
        }
    }
};

export const SIGN_OUT = "SIGN_OUT";
export const signOutAction = () => {
    return {
        type: "SIGN_OUT",
        payload: {
            isSignedIn: false,
            uid: "",
            username: ""
        }
    }
}

src/reducks/store/initialState.js

const initialState = {
    users: {
        isSignedIn: false,
        uid: "",
        username: ""
    }   
}

export default initialState

管理したいstateの初期状態を書く

src/reducks/users/reducers.js

import * as Actions from './actions'  <--- actionsファイル内のモジュールをすべてimport
import initialState from '../store/initialState'

export const UsersReducer = (state = intialState.users, action) => {  <--- ※2
    switch (action.type) {  <--- actions.jsのtypeごとに処理を変える
        case Actions.SIGN_IN:   <--- type: "SIGN_IN" であれば
            return {
                ...state,   <--- スプレッド構文 ※1
                ...action.payload
            }
        default:
            return state
    }
}

※2 … 第2引数のactionはactions.jsがreturnした値です

※1 … スプレッド構文とは

const payload = {
uid: “000”,
username: “michael”
}
console.log({…payload})
// {uid: “000”, username: “michael”}

つまり、スプレッド構文を使わない場合は次のようになります
return {
isSignedIn: true,
uid: userState.uid,
username: userState.username
}

src/reducks/store/store.js

次の2つのライブラリをインストールしてください

・react-router … Reactのルーティング用ライブラリ

・connected-react-router … Reduxのstoreでルーティングを管理するためのライブラリ

import { createStore as reduxCreateStore } from 'redux';
import { combineReducers } from 'redux';
import { applyMiddleware } from 'redux';
import { connectRouter, routerMiddleware } from 'connected-react-router';
import { ProductsReducer } from '../products/reducers';
import { UsersReducer } from '../users/reducers';


export default function createStore(history) {  <--- historyには
    return reduxCreateStore(                     --- 「Reactアプリ内でブラウザが今どこにいるのか」
        combineReducers({                        --- という情報が入っています
            router: connectRouter(history),
            users: UsersReducer,
        }),
        applyMiddleware(               <--- CombineReducersのrouterを
            routerMiddleware(history)  <--- middlewareとして使うという宣言
        )                              <--- です
    );
}

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { ConnectedRouter } from 'connected-react-router';
import * as History from 'history';
import { Provider } from 'react-redux';
import createStore from './reducks/store/store';
import * as serviceWorker from './serviceWorker';
import App from './App';

const history = History.createBrowserHistory();
export const store = createStore(history);  <--- store.jsの関数

ReactDOM.render(
    <Provider store={store}>  <-- Providerタグにstore.jsのreturn値を渡す
        <ConnectedRouter history={history}>  <-- ConnectedRouterタグにブラウザの現在位置historyを渡す
            <App />
        </ConnectedRouter>
    </Provider>,
    document.getElementById('root'),
)
serviceWorker.unregister();

src/App.jsx(jsからjsxにリネーム)

import React from 'react';
import Router from './Router';

const App = () => {
    return (
        <main>
            <Router />
        </main>
    );
}

export default App;

src/Router.jsx

import React from 'react';
import { Route, Switch } from 'react-router';
import { Login, Home } from 'templates';

const Router = () => {
    return (
        <Switch>
            <Route exact path="/login" component={Login} />
            <Route exact path="(/)?" component={Home} />  <-- ()?は()内の文字列があってもなくても良いという意味
        </Switch>
    );
}
export default Router;

src/templates/Login.jsx

import React from 'react';
import { useDispatch } from 'react-redux';
import { push } from 'connected-react-router';  <--- pushはURLを遷移する機能

const Login = () => {
    const dispatch = useDispatch();
    return (
        <div>
            <h2>LOGIN</h2>
            <button onClick={ () => dispatch(push('/')) }>  <--- push('/')でホームに遷移する
                LOGIN
            </button>
        </div>
    );
};

src/templates/Home.jsx

import React from 'react';

const Home = () => {
    return (
        <h2>HOME</h2>
    );
}
export default Home

src/templates/index.js(エントリポイント)

export {default as Home} from './Home';
export {default as Login} from './Login';
BACK