今回も前回の続きからです。
ルーティングの設定(middlewareの導入)
ルーティング用ライブラリー
1、react-router(Reactのルーティング用ライブラリー)
2、connected-react-router(ReduxのStoreでルーティング管理)
middlewareの導入
store.js
import {
createStore as reduxCreateStore,
combineReducers,
applyMiddleware
} from "redux";
import{ connectRouter, routerMiddleware} from "connected-react-router";
export default function createStore(history) {
return reduxCreateStore(
combineReducers({
router: connectRouter(history),
users: UsersReducer
}),
applyMiddleware(
routerMiddleware(history)
)
)
}
//historyは今いるURLの場所、パスの状態ということ?
//以下はReduxのStoreにstateを生成してhistoryのパスはどこなのかを指している。
combineReducers({
router: connectRouter(history),
users: UsersReducer
}),
// 以下はrouterをMiddlewareとして使いますよ〜と宣言している。
applyMiddleware(
routerMiddleware(history)
)
StoreとRouterの接続
⇨以下までできたら、storeにルーティングの情報を持たせることができる。
index.js
import {ConnectedRouter} from 'connected-react-router';
import * as History from 'history';
const history = History.createBrowserHistory();
export const store = createStore(history);
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
//createBrowserHistory()は現在のブラウザのULR(パス)を取得する。
//Appコンポーネントをラッピングしてパスが変わった時点でstateも変更できる
Routerコンポーネントを作る
⇨ブラウザのURLによってコンポーネントが切り替わる。
src/Router.jsx
import React from 'react';
import {Switch, Route} from 'react-router';
import {Login, Home} from './templates';
const Router = () => {
return(
<Switch>
<Route exact path={ "/login" } component={Login} />
<Route exact path={ "(/)?" } component={Home} />
</Switch>
)
}
Switchとexactはセットの考え方でいいが、
⇨もしexactがない場合、pathが部分一致で遷移するということだけ頭に入れたほうがいい。
⇨セットとして使う場合はURLと完全一致した時に遷移するということ。
使わない場合は例である。
ブログ記事のような投稿にそれぞれにidが付いている時など。
<Route path="/posts/:id" component={Post} />
templatesファイル作成
import React from 'react';
import {useDispatch} from 'react-redux';
import {push} from "connected-react-router";
const Login = () => {
const dispatch = useDispatch();
return (
<div>
<h2>ログイン</h2>
<button onClick={() => dispatch(push('/'))} >ログイン</button>
</div>
);
}
export default Login
re-ducksパターンでファイル管理
メリット
1、actionsとreducersがシンプルになる
2、ファイルが肥大化しにくくなる。
3、ファイルごとの役割が明確になり管理しやすい。
各ファイルの役割
operations
1、複雑な処理を任せられる
2、redux-thunkで非同期処理の制御を行う
3、Actionsを呼び出す。
例
onClickイベントでoperationsに定義している関数呼び出し、何か処理を行い、このoperationsファイルからActionsを呼び出す。Actionsは単純にreducersにどんなデータを渡すか、そしてreducersはStoreのstateを変更してくださいね〜という流れ。
types
1、TypeScriptで使う
2、型定義を記述するしてexport
selectors
1、Storeで管理しているstateを参照する関数
2、reselectというnpmモジュールを使う。
users/selectors.js
import {createSelector} from 'reselect';
const useSelector = (state) => state.users;
export const getUserId = createSelector(
[useSelector],
state => state.uid
)
//Storeのstateのusersのuidをこの関数で呼び出している。
例(今回はHome.jsxに上記のgetUserIdを呼び出し、uidの表示)
import React from 'react';
import {getUserId} from '../reducks/users/selectors';
import {useSelector} from 'react-redux';
const Home = () => {
const selector = useSelector(state => state);
const uid = getUserId(selector);
return(
<div>
<h2>HOME</h2>
<p>{uid}</p>
</div>
)
}
export default Home;
//selectorにStoreのstateを入れる。
//getUserIdの引数にselectorを入れて使う形。
redux-thunk
⇨Reduxで非同期処理を制御するライブラリー
store.js
import thunk from 'redux-thunk';
例
applyMiddleware(
routerMiddleware(history),
thunk
)
Reduxは学習は基本的に終了です。
ありがとうございました。