网站建设网络课程,郑州企业建筑设计软件,编程一个最简单游戏代码,浙江省杭州市软装设计公司前言 
createMemoryRouter 是 React Router 提供的一种特殊路由器#xff0c;它将路由状态存储在内存中而不是浏览器的 URL 地址栏中。 这种路由方式特别适用于测试、非浏览器环境#xff08;如 React Native#xff09;以及需要完全控制路由历史的场景。 
一、createMemory…前言 
createMemoryRouter 是 React Router 提供的一种特殊路由器它将路由状态存储在内存中而不是浏览器的 URL 地址栏中。 这种路由方式特别适用于测试、非浏览器环境如 React Native以及需要完全控制路由历史的场景。 
一、createMemoryRouter 的主要用途 
测试环境在单元测试和集成测试中模拟路由行为非浏览器环境在 React Native、Electron 或 Node.js 服务器端渲染中使用组件沙盒在 Storybook 或类似工具中独立运行路由组件路由历史控制需要编程式控制完整路由历史的场景无 URL 环境在不需要地址栏显示路由变化的应用中使用 
二、createMemoryRouter 与 createBrowserRouter 的关键区别 三、createMemoryRouter 完整代码示例 
3.1、 基础路由配置 
// src/MemoryRouterDemo.jsx
import React from react;
import {createMemoryRouter,RouterProvider,Link,Outlet,useLocation
} from react-router-dom;// 页面组件
function Home() {return (div classNamepageh1首页/h1p欢迎使用内存路由示例/pdiv classNamepage-navLink to/about classNamenav-link关于我们/LinkLink to/products classNamenav-link产品列表/Link/div/div);
}function About() {return (div classNamepageh1关于我们/h1p我们是一家专注于前端技术的公司/pLink to/ classNameback-link返回首页/Link/div);
}// 布局组件
function RootLayout() {const location  useLocation();return (div classNameappheader classNameapp-headerh1 classNamelogo内存路由示例/h1div classNameurl-display当前路由: code{location.pathname || /}/code/divnav classNamemain-navLink to/ classNamenav-item首页/LinkLink to/about classNamenav-item关于/LinkLink to/products classNamenav-item产品/Link/nav/headermain classNameapp-contentOutlet / {/* 子路由渲染位置 */}/mainfooter classNameapp-footerp当前使用: codecreateMemoryRouter/code | 路由历史: {location.key}/p/footer/div);
}// 创建内存路由配置
const router  createMemoryRouter([{path: /,element: RootLayout /,children: [{index: true,element: Home /},{path: about,element: About /},{path: products,element: ProductsList /}]}
], {initialEntries: [/], // 初始路由initialIndex: 0 // 初始路由索引
});// 产品列表组件
function ProductsList() {const products  [{ id: 1, name: React 教程, price: 99 },{ id: 2, name: Node.js 实战, price: 129 },{ id: 3, name: TypeScript 指南, price: 89 }];return (div classNamepageh1产品列表/h1div classNameproducts-grid{products.map(product  (div key{product.id} classNameproduct-cardh3{product.name}/h3p价格: ¥{product.price}/p/div))}/divLink to/ classNameback-link返回首页/Link/div);
}// 导出使用内存路由的应用
export default function MemoryRouterDemo() {return RouterProvider router{router} /;
}3.2、 在 Storybook 中使用 createMemoryRouter 
// src/stories/UserProfile.stories.jsx
import React from react;
import { createMemoryRouter, RouterProvider } from react-router-dom;
import UserProfile from ../components/UserProfile;export default {title: UserProfile,component: UserProfile,
};// 模板函数
const Template  (args)  {// 创建内存路由const router  createMemoryRouter([{path: /user/:userId,element: UserProfile {...args} /,loader: ()  ({user: {id: 123,name: 张三,email: zhangsanexample.com,joinDate: 2022-01-15}})}], {initialEntries: [/user/123],initialIndex: 0});return RouterProvider router{router} /;
};// 默认状态
export const Default  Template.bind({});
Default.args  {};// 加载状态
export const LoadingState  Template.bind({});
LoadingState.args  {// 模拟延迟加载loader: ()  new Promise(()  {})
};// 错误状态
export const ErrorState  Template.bind({});
ErrorState.args  {loader: ()  {throw new Error(无法加载用户数据);}
};3.3、 在测试中使用 createMemoryRouter 
// src/tests/LoginPage.test.jsx
import React from react;
import { render, screen, fireEvent } from testing-library/react;
import { createMemoryRouter, RouterProvider } from react-router-dom;
import LoginPage from ../components/LoginPage;describe(LoginPage, ()  {// 创建登录页路由const createLoginRouter  (initialEntries  [/login])  {return createMemoryRouter([{path: /login,element: LoginPage /},{path: /dashboard,element: div仪表盘页面/div}], {initialEntries,initialIndex: 0});};test(渲染登录表单, ()  {const router  createLoginRouter();render(RouterProvider router{router} /);expect(screen.getByLabelText(用户名)).toBeInTheDocument();expect(screen.getByLabelText(密码)).toBeInTheDocument();expect(screen.getByRole(button, { name: 登录 })).toBeInTheDocument();});test(显示验证错误, async ()  {const router  createLoginRouter();render(RouterProvider router{router} /);fireEvent.click(screen.getByRole(button, { name: 登录 }));expect(await screen.findByText(请输入用户名)).toBeInTheDocument();expect(await screen.findByText(请输入密码)).toBeInTheDocument();});test(成功登录后导航到仪表盘, async ()  {const router  createLoginRouter();render(RouterProvider router{router} /);// 填写表单fireEvent.change(screen.getByLabelText(用户名), {target: { value: testuser }});fireEvent.change(screen.getByLabelText(密码), {target: { value: password123 }});// 提交表单fireEvent.click(screen.getByRole(button, { name: 登录 }));// 验证导航expect(await screen.findByText(仪表盘页面)).toBeInTheDocument();});
});3.4、 在 React Native 中使用 createMemoryRouter 
// App.js (React Native)
import React from react;
import { View, Text, Button, StyleSheet } from react-native;
import { createMemoryRouter, RouterProvider, Link, Outlet } from react-router-dom-native;// 创建自定义导航组件
function NativeLink({ to, children }) {return (Button title{children} onPress{()  router.navigate(to)} /);
}// 页面组件
function HomeScreen() {return (View style{styles.container}Text style{styles.title}首页/TextNativeLink to/about关于我们/NativeLink/View);
}function AboutScreen() {return (View style{styles.container}Text style{styles.title}关于我们/TextText我们是一家移动应用开发公司/TextNativeLink to/返回首页/NativeLink/View);
}// 创建内存路由
const router  createMemoryRouter([{path: /,element: (View style{styles.app}Outlet //View),children: [{index: true,element: HomeScreen /},{path: about,element: AboutScreen /}]}
]);// 应用入口
export default function App() {return RouterProvider router{router} /;
}const styles  StyleSheet.create({app: {flex: 1,padding: 20,backgroundColor: #f5f5f5},container: {flex: 1,justifyContent: center,alignItems: center,},title: {fontSize: 24,fontWeight: bold,marginBottom: 20}
});3.5、 高级路由历史操作 
// src/HistoryDemo.jsx
import React, { useState, useEffect } from react;
import {createMemoryRouter,RouterProvider,useLocation,useNavigate
} from react-router-dom;// 历史控制组件
function HistoryController() {const location  useLocation();const navigate  useNavigate();const [history, setHistory]  useState([]);useEffect(()  {setHistory(prev  [...prev, location]);}, [location]);const goBack  ()  navigate(-1);const goForward  ()  navigate(1);return (div classNamehistory-controlsdiv classNamehistory-buttonsbutton onClick{goBack} disabled{history.length  1}后退/buttonbutton onClick{goForward} disabled{history.length  1}前进/button/divdiv classNamehistory-listh3路由历史:/h3ul{history.map((entry, index)  (li key{entry.key} className{index  history.length - 1 ? current : }{entry.pathname}/li))}/ul/div/div);
}// 页面组件
function Dashboard() {return (div classNamepageh1仪表盘/h1HistoryController //div);
}function Settings() {return (div classNamepageh1设置/h1HistoryController //div);
}function Profile() {return (div classNamepageh1个人资料/h1HistoryController //div);
}// 创建内存路由
const router  createMemoryRouter([{path: /,element: Dashboard /,},{path: /settings,element: Settings /,},{path: /profile,element: Profile /,}
], {initialEntries: [/, /settings, /profile],initialIndex: 0
});// 导出应用
export default function HistoryDemo() {return RouterProvider router{router} /;
}四、createMemoryRouter 核心功能详解 
4.1、 创建和配置 
const router  createMemoryRouter(routes, options);参数: 
routes: 路由配置数组与 createBrowserRouter 相同options: 配置对象initialEntries: 初始历史记录数组默认为 [“/”]initialIndex: 初始条目的索引默认为最后一个索引basename: 应用的基础路径future: 未来标志配置hydrationData: 水合数据用于 SSR 
2.2、 路由历史操作 
内存路由提供完整的编程式历史控制 
// 导航到新路径
router.navigate(/new-path);// 添加历史记录
router.navigate(/new-path, { state: { data: 123 }, replace: false });// 后退
router.navigate(-1);// 前进
router.navigate(1);// 替换当前历史记录
router.navigate(/replaced-path, { replace: true });// 获取当前历史记录
const currentLocation  router.state.location;// 获取完整历史
const historyStack  router.state.history.entries;4.3、 在测试中使用 
test(导航到关于页, async ()  {// 创建内存路由const router  createMemoryRouter(routes, {initialEntries: [/],initialIndex: 0});render(RouterProvider router{router} /);// 初始状态验证expect(screen.getByText(首页)).toBeInTheDocument();// 执行导航act(()  {router.navigate(/about);});// 验证导航结果expect(screen.getByText(关于我们)).toBeInTheDocument();
});4.4. 在 Storybook 中使用 
// 创建带特定状态的组件
const Template  (args)  {const router  createMemoryRouter([{path: /product/:id,element: ProductDetail {...args} /,loader: ()  ({product: {id: 123,name: 高级产品,price: 299,description: 这是一个高级产品}})}], {initialEntries: [/product/123],initialIndex: 0});return RouterProvider router{router} /;
};// 错误状态
export const ErrorState  Template.bind({});
ErrorState.args  {loader: ()  {throw new Error(产品加载失败);}
};4.5、在 React Native 中集成 
import { createMemoryRouter, RouterProvider } from react-router-dom-native;const router  createMemoryRouter([{path: /,element: HomeScreen /,},{path: /details,element: DetailsScreen /,}
]);export default function App() {return RouterProvider router{router} /;
}五、createMemoryRouter 最佳实践 
5.1、 测试场景 
describe(认证流程, ()  {it(未登录用户重定向到登录页, async ()  {const router  createMemoryRouter(routes, {initialEntries: [/dashboard],});render(RouterProvider router{router} /);expect(await screen.findByText(登录页面)).toBeInTheDocument();});it(登录后导航到仪表盘, async ()  {const router  createMemoryRouter(routes, {initialEntries: [/login],});render(RouterProvider router{router} /);// 填写登录表单userEvent.type(screen.getByLabelText(用户名), testuser);userEvent.type(screen.getByLabelText(密码), password123);userEvent.click(screen.getByRole(button, { name: 登录 }));expect(await screen.findByText(仪表盘)).toBeInTheDocument();});
});5.2、 模拟特定路由状态 
// 模拟带状态的路由
const router  createMemoryRouter(routes, {initialEntries: [{ pathname: /checkout, state: { cart: [{ id: 1, name: 产品A, price: 99 },{ id: 2, name: 产品B, price: 149 }] } }],initialIndex: 0
});// 在组件中访问状态
function Checkout() {const location  useLocation();const cart  location.state?.cart || [];// ...
}5.3、 复杂历史操作 
// 创建包含多个条目的历史
const router  createMemoryRouter(routes, {initialEntries: [/, /products, /products/123],initialIndex: 2 // 当前在 /products/123
});// 后退到产品列表
router.navigate(-1);
expect(router.state.location.pathname).toBe(/products);// 前进回产品详情
router.navigate(1);
expect(router.state.location.pathname).toBe(/products/123);5.4、 错误边界测试 
it(显示加载错误, async ()  {// 创建会抛出错误的路由const router  createMemoryRouter([{path: /,element: Home /,errorElement: ErrorPage /},{path: /failing,element: FailingComponent /,loader: ()  {throw new Error(模拟加载错误);}}], {initialEntries: [/failing],initialIndex: 0});render(RouterProvider router{router} /);expect(await screen.findByText(发生错误)).toBeInTheDocument();expect(await screen.findByText(模拟加载错误)).toBeInTheDocument();
});六、使用场景推荐 
组件测试测试路由相关的组件逻辑Storybook 集成在隔离环境中展示路由组件React Native 应用在移动端实现路由功能Electron 应用在桌面应用中管理路由命令行工具为 CLI 工具添加路由功能服务端渲染测试模拟路由行为进行 SSR 测试游戏和多媒体应用不需要 URL 的路由场景教育演示展示路由工作原理而不影响浏览器历史 
总结 
createMemoryRouter 是 React Router 提供的一种灵活的路由解决方案 主要特点包括 
内存存储路由状态存储在内存中不依赖浏览器 URL完全控制提供完整的编程式历史管理环境无关可在任何 JavaScript 环境中使用测试友好简化路由相关组件的测试隔离环境适合在 Storybook 等工具中展示组件 
通过 createMemoryRouter我们可以在脱离浏览器环境的情况下获得完整的 React Router 功能特别适合测试和特殊环境下的路由需求。 文章转载自: http://www.morning.pwhjr.cn.gov.cn.pwhjr.cn http://www.morning.jksgy.cn.gov.cn.jksgy.cn http://www.morning.ckntb.cn.gov.cn.ckntb.cn http://www.morning.tqgx.cn.gov.cn.tqgx.cn http://www.morning.ctlzf.cn.gov.cn.ctlzf.cn http://www.morning.rwzqn.cn.gov.cn.rwzqn.cn http://www.morning.hlnrj.cn.gov.cn.hlnrj.cn http://www.morning.pyswr.cn.gov.cn.pyswr.cn http://www.morning.oioini.com.gov.cn.oioini.com http://www.morning.rbnnq.cn.gov.cn.rbnnq.cn http://www.morning.rmxgk.cn.gov.cn.rmxgk.cn http://www.morning.bmhc.cn.gov.cn.bmhc.cn http://www.morning.mnjwj.cn.gov.cn.mnjwj.cn http://www.morning.wpjst.cn.gov.cn.wpjst.cn http://www.morning.xhqwm.cn.gov.cn.xhqwm.cn http://www.morning.djpps.cn.gov.cn.djpps.cn http://www.morning.trzzm.cn.gov.cn.trzzm.cn http://www.morning.hlwzd.cn.gov.cn.hlwzd.cn http://www.morning.zdsqb.cn.gov.cn.zdsqb.cn http://www.morning.rcjwl.cn.gov.cn.rcjwl.cn http://www.morning.sfhjx.cn.gov.cn.sfhjx.cn http://www.morning.ycmpk.cn.gov.cn.ycmpk.cn http://www.morning.yjknk.cn.gov.cn.yjknk.cn http://www.morning.sftrt.cn.gov.cn.sftrt.cn http://www.morning.qpsdq.cn.gov.cn.qpsdq.cn http://www.morning.zshuhd015.cn.gov.cn.zshuhd015.cn http://www.morning.fwkjp.cn.gov.cn.fwkjp.cn http://www.morning.zsrjn.cn.gov.cn.zsrjn.cn http://www.morning.qnksk.cn.gov.cn.qnksk.cn http://www.morning.kczkq.cn.gov.cn.kczkq.cn http://www.morning.lokext.com.gov.cn.lokext.com http://www.morning.qrmry.cn.gov.cn.qrmry.cn http://www.morning.npbgj.cn.gov.cn.npbgj.cn http://www.morning.bfkrf.cn.gov.cn.bfkrf.cn http://www.morning.yhyqg.cn.gov.cn.yhyqg.cn http://www.morning.jlxqx.cn.gov.cn.jlxqx.cn http://www.morning.ydfr.cn.gov.cn.ydfr.cn http://www.morning.pcbfl.cn.gov.cn.pcbfl.cn http://www.morning.qbfqb.cn.gov.cn.qbfqb.cn http://www.morning.jhrlk.cn.gov.cn.jhrlk.cn http://www.morning.zlhbg.cn.gov.cn.zlhbg.cn http://www.morning.gqjqf.cn.gov.cn.gqjqf.cn http://www.morning.lgmty.cn.gov.cn.lgmty.cn http://www.morning.wjzzh.cn.gov.cn.wjzzh.cn http://www.morning.crkhd.cn.gov.cn.crkhd.cn http://www.morning.ylmxs.cn.gov.cn.ylmxs.cn http://www.morning.mgkb.cn.gov.cn.mgkb.cn http://www.morning.knlgk.cn.gov.cn.knlgk.cn http://www.morning.jfch.cn.gov.cn.jfch.cn http://www.morning.jjxnp.cn.gov.cn.jjxnp.cn http://www.morning.nwljj.cn.gov.cn.nwljj.cn http://www.morning.qmzwl.cn.gov.cn.qmzwl.cn http://www.morning.dbphz.cn.gov.cn.dbphz.cn http://www.morning.fqpyj.cn.gov.cn.fqpyj.cn http://www.morning.mgkcz.cn.gov.cn.mgkcz.cn http://www.morning.gtdf.cn.gov.cn.gtdf.cn http://www.morning.ktskc.cn.gov.cn.ktskc.cn http://www.morning.ckzjl.cn.gov.cn.ckzjl.cn http://www.morning.xqzrg.cn.gov.cn.xqzrg.cn http://www.morning.fdhwh.cn.gov.cn.fdhwh.cn http://www.morning.plznfnh.cn.gov.cn.plznfnh.cn http://www.morning.tntqr.cn.gov.cn.tntqr.cn http://www.morning.nkjnr.cn.gov.cn.nkjnr.cn http://www.morning.gpxbc.cn.gov.cn.gpxbc.cn http://www.morning.tfei69.cn.gov.cn.tfei69.cn http://www.morning.yydzk.cn.gov.cn.yydzk.cn http://www.morning.wmmtl.cn.gov.cn.wmmtl.cn http://www.morning.bcdqf.cn.gov.cn.bcdqf.cn http://www.morning.sbjhm.cn.gov.cn.sbjhm.cn http://www.morning.syssdz.cn.gov.cn.syssdz.cn http://www.morning.rsnn.cn.gov.cn.rsnn.cn http://www.morning.wjhnx.cn.gov.cn.wjhnx.cn http://www.morning.fqhbt.cn.gov.cn.fqhbt.cn http://www.morning.mtgkq.cn.gov.cn.mtgkq.cn http://www.morning.srkzd.cn.gov.cn.srkzd.cn http://www.morning.stprd.cn.gov.cn.stprd.cn http://www.morning.mdpkf.cn.gov.cn.mdpkf.cn http://www.morning.btpll.cn.gov.cn.btpll.cn http://www.morning.dbhnx.cn.gov.cn.dbhnx.cn http://www.morning.yrcxg.cn.gov.cn.yrcxg.cn