我的反应路由结构
背景
先决条件
问题
解决方案
结论
这篇文章最初发表在我的博客legobox上
背景
我经常构建前端应用程序和 API,通常会使用各种工具,但 React 一直是我感兴趣的工具,它能让我快速构建。虽然我可能会说 Vue 和 React 完全一样,但这不是今天的重点,关于 React 和 Vue 的废话就到此为止,所以我两个都用。它们都很棒,我很高兴还有其他框架可供选择。在使用 React 开发和创建应用程序的过程中,我为我的应用程序制定了一个通用的结构和路由模式。
我认为这是我愿意分享的东西,并希望通过社区的指导来改进。
先决条件
对于本文来说,只有两个先决条件,(上次我写了一个先决条件,它像野火一样传播开来,希望再次发生这种情况不会要求太多🙃)
- 您了解 React,并具有一定的使用经验。
- 你听说过 redux
- 您熟悉 React 路由器。
如果你明白了这一点,那么你就可以开始了。
问题
该问题需要使用 react-router 库在页面之间导航,同时还要跟踪身份验证状态,对于身份验证和导航,已经对这个问题有了共同的理解,通常我们知道可以通过简单设置 react router 和 redux 来解决这个问题,但是这个设置有很多模式,在本文中,我将解释我的。
解决方案
为了在应用程序中正确导航,我设置了 react-router 并实现了 3 个组件的身份验证检查流程,一个组件检查仅限访问者的页面,另一个组件检查受保护的路由,第三个组件包含所有内容并对应用程序的身份验证状态进行一般检查,我知道这听起来很模棱两可,但我们将回顾代码结构并深入了解事情的细节。
// import scenes here and make routes of them
import React from 'react';
import {Route} from 'react-router-dom';
// import scenes here
import {Dashboard, Settings, Login} from './Scenes'
// auth checkers for checking if the routes are authorized
import AppCheck from './Modules/AppCheck.jsx';
import EnsureLoggedInContainer from './Modules/EnsureLoggedInContainer.jsx';
import EnsureVisitorOnlyContainer from './Modules/EnsureVisitorOnlyContainer.jsx';
const routes = (
<React.Fragment>
<AppCheck>
<EnsureVisitorOnlyContainer>
<Route path="/login" component={Login} />
</EnsureVisitorOnlyContainer>
<EnsureLoggedInContainer>
<Route exact path="/home" component={Dashboard} />
<Route path="/settings" component={Settings} />
</EnsureLoggedInContainer>
</AppCheck>
</React.Fragment>
);
export default routes;
这是直接从代码库中提取的,正如您所见,这个想法已经清晰地呈现出来了。
在这种情况下,三个组成部分是AppCheck
,,EnsureVisitorOnlyContainer
。EnsureLoggedInContainer
让我们看一下这些组件的内部结构。
AppCheck 组件。
import React from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router";
class AppCheck extends React.Component {
componentDidUpdate(prevProps) {
const { dispatch, redirectUrl } = this.props;
const isLoggingOut = prevProps.isLoggedIn && !this.props.isLoggedIn;
const isLoggingIn = !prevProps.isLoggedIn && this.props.isLoggedIn;
if (isLoggingIn) {
// dispatch(navigateTo(redirectUrl))
} else if (isLoggingOut) {
// do any kind of cleanup or post-logout redirection here
}
}
render() {
return this.props.children;
}
}
const mapStateToProps = state => {
console.log(state);
return {
isLoggedIn: state.isAuthenticated,
redirectUrl: state.redirectUrl
};
};
export default withRouter(connect(mapStateToProps)(AppCheck));
我们可以看到,该组件在更新时检查 prop 并确认之前的状态isLoggedIn
,以注意用户是否正在登录或注销,根据此情况,它会重定向到 redux 设置中指定的另一个 url,或者如果它试图注销,它会继续注销,否则它会继续渲染 props 子项。
确保访客仅容器
import React from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router";
// import actions from "../Store/Actions";
class EnsureVisitorOnlyContainer extends React.Component {
componentDidMount() {
const { currentURL } = this.props;
var visitorRoutes = ["/", "", "terms", "conditions"];
var check = visitorRoutes.indexOf(currentURL) > -1;
if (this.props.isLoggedIn) {
// set the current url/path for future redirection (we use a Redux action)
// then redirect (we use a React Router method)
// dispatch(actions.setRedirectUrl(currentURL))
if (check) {
this.props.history.replace("/home");
}
}
}
render() {
if (!this.props.isLoggedIn) {
return this.props.children;
} else {
return null;
}
}
}
// Grab a reference to the current URL. If this is a web app and you are
// using React Router, you can use `ownProps` to find the URL. Other
// platforms (Native) or routing libraries have similar ways to find
// the current position in the app.
function mapStateToProps(state, ownProps) {
console.log(ownProps);
return {
isLoggedIn: state.isAuthenticated,
currentURL: ownProps.location.pathname
};
}
export default withRouter(connect(mapStateToProps)(EnsureVisitorOnlyContainer));
该组件集只是检查当前路线是否在访客路线之中,如果是,则检查登录状态,如果应用程序已登录,则将用户重定向到该/home
路线。
如果在访问者列表中找到其路径,则此组件集中列出的任何路线都将被重定向到主页路线。
确保登录容器
import React from 'react'
import {connect} from 'react-redux'
import { withRouter } from 'react-router'
import actions from '../Store/Actions'
class EnsureLoggedInContainer extends React.Component {
componentDidMount() {
const { dispatch, currentURL } = this.props
if (!this.props.isLoggedIn) {
// set the current url/path for future redirection (we use a Redux action)
// then redirect (we use a React Router method)
dispatch(actions.setRedirectUrl(currentURL))
this.props.history.replace("/")
}
}
render() {
if (this.props.isLoggedIn) {
return this.props.children
} else {
return null
}
}
}
// Grab a reference to the current URL. If this is a web app and you are
// using React Router, you can use `ownProps` to find the URL. Other
// platforms (Native) or routing libraries have similar ways to find
// the current position in the app.
function mapStateToProps(state, ownProps) {
console.log(ownProps)
return {
isLoggedIn: state.isAuthenticated,
currentURL: ownProps.location.pathname
}
}
export default withRouter(connect(mapStateToProps)(EnsureLoggedInContainer))
该容器检查应用程序的当前状态是否未登录,它会重定向到/
路径,因此所有页面都可以通过此结构进行管理。
AppCheck在 prevProp 改变其状态时处理注销过程,而EnsureVisitorsOnlyContainer和EnsureLoggedInContainer根据路由和列出的容器在不同的实例上处理重定向。
结论
我愿意接受有关如何改进的建议,并听取您如何实现您的目标,随着时间的推移,我希望分享我在使用 react 和 vue 开发中使用的其他技巧和技术,并帮助其他人学习如何充分利用框架来更快地进行构建。
鏂囩珷鏉ユ簮锛�https://dev.to/legobox/my-react-routing-struct-d8i