サスペンス+遅延ロードコンポーネント
コンポーネント操作の遅延ロードを一時停止します。 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);