action / reducer / store / index / App
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';