blog

reactでルートとreduxサブモジュールのスキルを一元管理する

redux-thunkは非同期の問題を解決します。 redux-loggerは開発環境での使用に限定されます。アクションが状態を変更するたびに、主要な情報をコンソールに出力するので、開発者が状態をトレ...

Nov 23, 2020 · 6 min. read
シェア

サスペンス+遅延ロードコンポーネント

コンポーネント操作の遅延ロードを一時停止します。 lazyはコンポーネントを遅延ロードするために使用します。コード分割の実装

その結果、OtherComponentが正常にロードされない場合、ロードエフェクトが発生します。

// antdでロードする。
import { Spin } from 'antd'; 
// 遅延ロードコンポーネント
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const App = () => {
 return (
 <Suspense fallback={<Spin size="large" className="layout__loading" />}>
 <OtherComponent />
 </Suspense>
 )
}

redux-thunk、redux-loggerミドルウェアの使用

  • redux-thunk 非同期の問題を解決します。
  • redux-loggerは開発環境での使用に限定されています。アクションが状態を変更するたびに、キーとなる情報をコンソールに出力するので、開発者が状態をトレースするのは簡単です。

1.州の倉庫

 // user.js
 const user = {
 user_name: ''
 }
 export default user;

2. レデューサー作業員

 // userReducer.js
 import (* as initState) from '../state/user'
 export default function app(state = initState, action) {
 const { type, payload } = action;
 switch (type) {
 case "SET_USER_NAME":
 return {
 ...state,
 user_name: payload,
 };
 default:
 return {
 ...state,
 };
 }
 }
 
 // index.js 
 import { combineReducers } from 'redux'
 import appReducer from './user'
 const rootReducer = combineReducers({
 user: userReducer
 })
 export default rootReducer;

3.アクション 操作されたデータ

export const login = (user) => ({
 type: 'SET_USER_NAME',
 payload: user,
})

4.店舗

import { createStore, applyMiddleware, compose } from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from './reducers'
const composeEnhancers =
 typeof window === 'object' &&
 window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
 }) : compose
const middlewares = [
 thunkMiddleware
]
if (process.env.NODE_ENV === 'development') {
 middlewares.push(reduxLogger);
}
const enhancer = composeEnhancers(
 applyMiddleware(...middlewares)
)
export function configStore() {
 const store = createStore(rootReducer, enhancer)
 return store
}
const store = configStore()
export export store

5.マウント

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './store';
ReactDOM.render(
 <Provider store={store}>
 <App />
 </Provider>,
 document.getElementById('root'),
);

6.使用

 import { connect } from 'react-redux'
 import { login } from "@/store/action/user"
 const Home = (props) => {
 const onSubmit = (userInfo) => {
 props.login(userInfo)
 }
 return (
 <button type="button" onClick={() => onSubmit()}"> </button>
 )
 }
 // 属性のマッピング
 const mapStateToProps = ({ user }) => ({
 user_name: user.user_name
 })
 // メソッドのマッピング
 const maoDispatchToProps = () => ({
 login
 })
 export default connect(mapStateToProps, maoDispatchToProps)(Home)

react-router集中管理ソリューションの場合

React-routerの集中管理でルーティングの構造がより見える化

ルータ・ルーティング構造

import React from 'react';
/**
 * ルーティングの最初のレベルは、ルートレンダリングの一番外側のレベルを担当する
 * path  
 * component コンポーネントの遅延ロード状況
 * meta.title タイトルは、また、ルートのサイドバーの値にすることができる
 * meta.icon ルートサイドバーアイコン
 * meta.auth パーミッションが必要なルート
 */
const routes = [
 {
 path: '/login',
 component: React.lazy(() => import('../views/login')),
 meta: {
 title: ' ',
 },
 },
 {
 path: '/',
 component: React.lazy(() => import('../layout/index')),
 redirect: '/home/index',
 children: [
 {
 path: '/home/index',
 component: React.lazy(() => import('../views/home')),
 meta: {
 title: ' ',
 auth: ['admin'],
 icon: 'read',
 },
 },
 {
 path: '*',
 auth: false,
 component: React.lazy(() => import('../views/error/404')),
 meta: {
 title: 'ページが存在しない',
 },
 },
 ],
 },
 
];
export default routes;

ルーター解析

import routes from './index';
/**
 *
 * ルートを一次元配列に変換する
 * @param routeList  
 * @param deep 深い変換かどうか
 * @param auth ルートが認証をチェックする必要があるかどうか、ルート設定の認証優先度はここより高い
 */
export function flattenRoute(routeList, deep, auth) {
 const result = [];
 for (let i = 0; i < routeList.length; i += 1) {
 const route = routeList[i];
 // ルートを追加する
 result.push({
 ...route
 });
 // ディープトラバーサル
 if (route.children && deep) {
 result.push(...flattenRoute(route.children, deep, auth));
 }
 }
 return result;
}
function getLayoutRouteList() {
 return flattenRoute(routes, false, false);
}
function getBusinessRouteList() {
 const routeList = routes.filter(route => route.path === '/');
 if (routeList.length > 0) {
 return flattenRoute(routeList, true, true);
 }
 return [];
}
// 一番外側のルートを解析する
export const layoutRouteList = getLayoutRouteList();
// のビジネスルートを解析する / ルート下のビジネスルート
export const businessRouteList = getBusinessRouteList();
// ルートのタイトルを取得する
export function getPageTitle(routeList) {
 const route = routeList.find(child => child.path === window.location.pathname);
 return (route && route.meta )? route.meta.title : '';
}

レイヤ1ルートの解析

最初に知っておくべきことは、ルートの最初のレベルはapp.jsxに配置できるルートコンポーネントに配置する必要があるということです。今回はルート/loginと/の最初のレベルを取得しますが、もちろん他のルートを配置することもできます。

import React, { Suspense } from 'react';
import { Spin } from 'antd';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { layoutRouteList } from './router/utils';
function App() {
 return (
 <Suspense 
 fallback={<Spin size="large" className="layout__loading" />}
 >
 <Router>
 <Switch>
 {layoutRouteList.map((route) => (
 <Route
 key={route.path}
 path={route.path}
 component={route.component}
 ></Route>
 ))}
 </Switch>
 </Router>
 </Suspense>
 );
}
export default App;

深い分析ルーティング

ルート解像度の最初のレイヤーによると、必然的に/ルートに移動し、この時点でコンポーネントの対応するコンポーネントは、レイアウトです。メインはMainRoutesで、ルートはこの場所に配置されます。

// LayoutRouter.jsx
import React from "react";
import MainRoutes from "./components/MainRoutes";
const LayoutRouter = () => {
 return (
 <Layout>
 <Silder />
 <Layout>
 <Header />
 <Content>
 <MainRoutes/>
 </Content>
 </Layout>
 </Layout>
 )
}
import React, { memo } from "react";
import { Route, Switch, useHistory } from "react-router-dom";
import DocumentTitle from "react-document-title";
import { connect } from "react-redux";
import { businessRouteList, getPageTitle } from "../../router/utils";
import CheckRouter from "./CheckRouter";
function MainRoutes({ role }) {
 const { location } = useHistory();
 const handleFilter = (route) => {
 if (role === "admin") {
 // 管理者 全てを見る
 return true;
 }
 if (!route.meta) {
 // metaスキップする値がない
 return true;
 }
 if (!route.meta.auth) {
 // authスキップする値がない
 return true;
 } else {
 // auth値チェックがある
 return route.meta.auth.includes(role)
 }
 };
 return (
 <DocumentTitle title={getPageTitle(businessRouteList)}>
 <Switch location={location}>
 { businessRouteList.map((route) => {
 const { component: Component } = route;
 return (
 handleFilter(route) && (
 <Route
 key={route.path}
 exact={route.path !== "*"}
 path={route.path}
 render={(props) => (
 <CheckRouter {...props} route={route}>
 <Component {...props} />
 </CheckRouter>
 )}
 ></Route>
 )
 );
 })}
 </Switch>
 </DocumentTitle>
 );
}
// ログイン時に取得するロール
const mapStateToProps = ({ user }) => ({
 role: user.role,
});
export default connect(mapStateToProps)(memo(MainRoutes));
import React, { memo } from 'react';
import { Redirect } from 'react-router-dom';
import { getToken } from '../../utils/cookie';
function CheckRouter(props) {
 //  
 if (!getToken()) {
 return (
 <Redirect
 to={`/login?redirectURL=${encodeURIComponent(
 window.location.origin +
 props.location.pathname +
 props.location.search,
 )}`}
 />
 );
 }
 if (props.route.redirect) {
 return <Redirect to={props.route.redirect} push />;
 }
 return <>{props.children}</>;
}
export default memo(CheckRouter);

Read next

データ構造|30行のコード、手を取り合ってTrieツリーを実装しよう

アルゴリズムとデータ構造」の第28回目は、古典的な文字列処理のデータ構造であるトライについてです。 4回にわたってゲーム理論に関するアルゴリズムをいくつか紹介しましたが、その中で最も広く使われ、最も重要なのは最後のSG関数です。これらを理解した後、一般的なゲーム理論のアルゴリズムを扱えば十分です。ゲーム理論は、それ自体が一つの学問分野であり、その中にはこのような...

Nov 23, 2020 · 6 min read

NIO入門

Nov 22, 2020 · 2 min read

エレメント-UI

Nov 22, 2020 · 1 min read

javaSriptの基本 - this

Nov 22, 2020 · 4 min read