使用 React Router V6 了解会话管理
使用 React Router V6 了解会话管理
React 根本不需要任何介绍,在这里我不打算描述它是什么以及如何工作的。我试图更详细地介绍 React 应用程序架构的主要方面,这将在未来帮助您快速构建一个易于扩展的项目。我们已经准确地开发了使用 React Router v6 构建应用程序的架构部分。
另外,我将使用 样式化组件
并且在文章的最后,您可以获取到存储库的 GitHub 链接。
应用结构
在开始任何编程操作之前,最好准确地确定应用程序中将涉及的所有路由。使用一些图表计划可以更好地进行研究,您可以在其中查看应用程序的整体概况。
此外,重要的是要明确哪些路线必须受到保护。保护是指用户只有在获得授权的情况下才能访问特定路由。如果你没有被授权,换句话说没有登录,那么你就不能访问那个路由。
也是重定向的一个非常重要的部分。例如,如果你有授权,如果你要去家乡路线,会发生什么?你应该被重定向到哪里?所有这些 重定向规则 应在开始时识别。让我们看一下带有应用程序路由模式的图表。
路由结构示意图
最初,区分受保护的和公共的路线很重要。这里绿色表示公共,红色表示受保护。此外,您可以找到一些带有受保护路径的绿色框,这意味着这些受保护的路径将具有不同的重定向逻辑。
如果您进入第二步注册而没有在第一步提供日期,则必须在第一步进行重定向。
作品
导航在所有路线中都很常见,但取决于 会议
.如果用户获得授权,链接堆栈将有所不同。这样,所有路线都可以更好地结束 主布局
您将在哪里拥有生命周期和会话注入的逻辑,当然还有在标题导航中显示的内容。重要的是要了解状态取决于授权。
布局
在我们的例子中,所有 看法
组件除了 未找到
和 导航
组件取决于 会议
.这意味着将显示 装载机
在暴露组件之前,以便清楚要呈现的内容。文件夹结构包含一堆用于进行 API 调用的组件、常量和伪造品。
应用程序架构样板
├── package.json
└── 源
├── App.js
├── __mocks__
│ └── db.mock.js
├── 组件
│ ├── Footer.js
│ ├── Loading.js
│ ├── MainLayout.js
│ ├── Navigation.js
│ ├── ProtectedRoute.js
│ └── PublicRoute.js
├── 常数
│ └── index.js
├── 假的
│ ├── fakeApi.js
│ └── fakeCache.js
├── 挂钩
│ └── useSession.js
└── index.js
数据请求
如您所见,我们将为我们的应用程序使用假 API。实际上,它可以是 Apollo 客户端或 REST API 调用,但在我们的例子中,我们将使用 承诺
和 暂停
为了 1s
请求延迟。我们必须处理登录和注销的身份验证,并从虚假 API 请求当前会话。最终,它是一个包含大量有用方法的简单类。
从'src/__mocks__/db.mock'导入{db};
从'./fakeCache'导入{ fakeCache }; 类 FakeApi {
静态请求时间 = 1000;
静态 KEY_CACHE = '缓存';
静态数据库 = 数据库; 上下文 = {}; 构造函数(){
常量上下文 = fakeCache.getItem(FakeApi.KEY_CACHE);
如果(上下文){
this.context = 上下文;
}
} 静态 userById = id => FakeApi.DB.find(user => user.id === id); #asyncRequest = 回调 =>
新的承诺(解决 => {
设置超时(()=> {
常量结果 = 回调();
解决(结果);
}, FakeApi.REQUEST_TIME);
}); 获取会话(){
返回 this.#asyncRequest(() => this.context.session);
} 登录() {
this.context.session = FakeApi.userById(1);
fakeCache.setItem(FakeApi.KEY_CACHE, this.context);
返回 this.getSession();
} 登出() {
this.context = {};
fakeCache.clear();
返回这个。#asyncRequest(() => null);
}
} 出口 const fakeApi = new FakeApi();
您可以在 构造函数
我们正在使用缓存。这是因为我们的请求必须有一个用于响应的缓存,并使用缓存作为下一个请求的提前以提高性能。这个实现非常粗略和简单,但很容易理解它的要点。
流程是,一旦我们调用,我们必须创建一个会话,并且 登出
同时清除会话和缓存。每个 异步请求
应该有一个 REQUEST_TIME
作为我们请求的假延迟。但是缓存呢?
出口常量 fakeCache = {
获取项目(键){
返回 JSON.parse(localStorage.getItem(key));
}, 设置项(键,值){
localStorage.setItem(key, JSON.stringify(value));
}, 清除() {
localStorage.clear();
},
};
对于存储/缓存数据,我们将使用 本地存储
.这只是一个带有方法的简单对象,没有别的。
路由
路由器部分必须关心我们 私人的
和 上市
路线。重定向必须从 私人的
当我们试图访问 /登录
如果用户在没有会话的情况下转到某个私有路由,它必须重定向到 /登录
.
"/" // -> 主视图取决于会话
"/about" // -> 关于显示有会话和无会话
"/login" // -> 仅显示无会话登录
"/signup" // -> 仅在没有会话的情况下注册节目
"/forgot-password" // -> 只显示没有会话的忘记密码
"/account" // -> 用户只显示会话
"/settings" // -> 设置只显示会话
"/posts" // -> 帖子和嵌套路由仅显示会话
"*" // -> Not Found 显示完全没有依赖关系
您可以看到针对每条路线的评论描述了可访问性的行为。进去的理由是什么 报名
如果你已经有一个会话?我在其他项目中多次看到这个问题。所以,在我们的例子中,我们将有一个重定向和从 受保护的路由
并从 公共路线
.仅有的 未找到视图
最后应该有完全的访问权限。
<Routes>
<Route element={<MainLayout /> }>
<Route path="/" element={<HomeView /> } />
<Route path="/about" element={<AboutView /> } />
<Route
路径="/登录"
元素={ <PublicRoute element={<LoginView /> } />}
/>
<Route
路径="/注册"
元素={ <PublicRoute element={<SignUpView /> } />}
/>
<Route
路径="/忘记密码"
元素={ <PublicRoute element={<ForgotPasswordView /> } />}
/>
<Route
路径="/帐户"
元素={
<ProtectedRoute
元素={ <ProtectedRoute element={<UserView /> } />}
/>
}
/>
<Route
路径="/设置"
元素={ <ProtectedRoute element={<SettingsView /> } />}
/>
<Route path="/posts" element={<ProtectedRoute /> }>
<Route index element={<PostsView /> } />
<Route path=":uuid" element={<PostView /> } />
</Route>
</Route>
<Route path="*" element={<NotFoundView /> } />
</Routes>
如您所见,我们为这两个流添加了保护。 受保护的路由
将导航到 /登录
在没有会话的情况下 公共路线
将重定向到 /
, 因为 主页查看
必须检查授权。
常量 HomeView = () => {
常量会话 = useOutletContext();
返回会话数据?<ListsPostsView /> :<LandingView /> ;
};
这 会议
可以得到正确的形式 使用OutletContext()
这是因为 主布局
将提供 语境
.
主要布局
一切都包裹在 主布局
这将提供 语境
的 会议
和其他全球相关数据。为了 主布局
我们将使用常见的 路线
和下 出口
将公开所有路线。让我们看一下设置。
常量 MainLayout = ({ 导航 }) => {
常量会话 = useSession(); 返回 (
<StyledMainLayout>
{!session.loading ? (
<div>
<Navigation session={session} navigate={navigate} />
<StyledContainer isLoggedIn={!!session.data}>
<Outlet context={session} />
</StyledContainer>
</div>
) : (
<Loading />
)}
<Footer />
</StyledMainLayout>
);
};
这 页脚
没有状态依赖,我们将一直渲染它。但 导航
并且所有嵌套路由都必须能够访问 会议
.这里是 出口
渲染子路由元素以及在哪里传递 语境
给所有的孩子。
向我们提供的请求 会议
数据有延迟响应,在这种情况下,我们显示 正在加载
零件。
会议
当应用程序被挂载时,我们必须请求当前 会议
.这 使用会话
钩子会在坐骑上开火并获得 会议
来自缓存或 API。
导出 const useSession = () => {
常量缓存 = fakeCache.getItem(SESSION_KEY);
const [数据,setData] = useState(缓存);
const [加载,setLoading] = useState(false); 使用效果(()=> {
如果(!缓存){
设置加载(真);
}
假API
.getSession()
.then(会话 => {
如果(会话){
设置数据(会话);
fakeCache.setItem(SESSION_KEY, session);
} 别的 {
设置数据(空);
fakeCache.clear();
}
})
.finally(() => {
设置加载(假);
});
}, []); 返回{数据,setData,加载};
};
每一个 假API
请求我们将响应存储到缓存中,例如存储在真实网站中的 cookie。然后是时候展示取决于 会议
这 导航
和 登录
/ 登出
和子组件。
导航
国家为 导航
在当前请求期间启用或禁用按钮很重要。如果打 登出
最好禁用所有按钮,以防止会话清除期间的其他操作。
导出常量导航 = ({ 导航,会话 }) => {
常量 [isLoading, setLoading] = useState(false); 常量 onLogin = async () => {
设置加载(真);
const sessionData = await fakeApi.login();
session.setData(sessionData);
fakeCache.setItem(SESSION_KEY, sessionData);
设置加载(假);
导航('/');
}; 常量 onLogout = async () => {
设置加载(真);
fakeCache.clear();
等待 fakeApi.logout();
session.setData(null);
设置加载(假);
导航('/');
}; 返回 (
<StyledNavigation>
<Link to="/">家</Link>
{会话数据? (
<div>
<Link to="/posts">帖子</Link>
<Link to="/settings">设置</Link>
<Link to="/account">我的简历</Link>
<button disabled={isLoading} onClick={onLogout}>
{正在加载? “正在加载...”:“注销”}
</button>
</div>
) : (
<div>
<Link to="/about">关于</Link>
<Link to="/signup">报名</Link>
<button disabled={isLoading} onClick={onLogin}>
{正在加载? '加载中...' : '登录'}
</button>
</div>
)}
</StyledNavigation>
);
};
私人和公共
很明显,路由应该受到保护,具体取决于 会议
,但如何得到 语境
在每个路由组件中?我们仍将借助上下文 使用OutletContext()
由...提供 反应路由器
API。
出口 const ProtectedRoute = ({ element }) => {
常量会话 = useOutletContext();
返回会话数据? (
元素 ||<Outlet />
) : (
<Navigate to="/login" replace />
);
};
为了 公共路线
一切都几乎相同,但另一种方式是使用不同的重定向路线。
出口 const PublicRoute = ({ element }) => {
常量会话 = useOutletContext();
返回会话数据?<Navigate to="/" replace /> : 元素 ||<Outlet /> ;
};
可能你可以看到,最好有类似的东西 智能路线
哪里最好只提供重定向的路线和道具来识别它是 上市
或者 私人的
.为了将来的可扩展性,我更喜欢分离这样的逻辑。差不多就是这样。
结论
React Router 是 React 应用程序最流行的路由解决方案,为当今的开发人员提供了最明显和最清晰的 API。由于上一个版本的惊人更新,构建路由架构变得更加容易和方便。希望应用程序的这种结构旨在帮助快速构建未来 React 项目的主体。谢谢你。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通