当前位置: 首页 > news >正文

网站建设太金手指六六二七wordpress 置顶标签

网站建设太金手指六六二七,wordpress 置顶标签,网站建设网课,网站主页设计布局图React学习笔记 React系列笔记学习 上篇笔记地址#xff1a;【超全】React学习笔记 上#xff1a;基础使用与脚手架 中篇笔记地址#xff1a;【超全】React学习笔记 中#xff1a;进阶语法与原理机制 React路由概念与理解使用 1. 引入 React路由是构建单页面应用(SPA, Sin…React学习笔记 React系列笔记学习 上篇笔记地址【超全】React学习笔记 上基础使用与脚手架 中篇笔记地址【超全】React学习笔记 中进阶语法与原理机制 React路由概念与理解使用 1. 引入 React路由是构建单页面应用(SPA, Single Page Application)中的核心技术之一它允许用户在不重新加载整个页面的情况下实现页面的切换。通过React路由开发者可以为用户提供丰富的页面导航体验同时保持应用的性能和响应速度。 路由的基本使用: React路由通过定义一组路由规则将URL与应用中的特定组件关联起来。用户通过点击链接或直接在浏览器中输入URL可以快速导航到应用的不同部分。 路由的执行过程: 了解React路由的执行过程有助于开发者理解路由是如何工作的以及在遇到问题时如何调试和解决路由相关的问题。 编程式导航: 除了通过链接导航React路由还提供了编程式导航的能力开发者可以通过代码来控制应用的导航行为使应用能够根据用户的操作或其他条件动态地导航到不同的页面。 默认路由: 默认路由允许开发者为应用定义一个默认的页面当用户访问的URL与任何已定义的路由规则都不匹配时应用会自动导航到这个默认页面。 匹配模式: React路由提供了多种匹配模式使开发者能够灵活地控制路由规则匹配不同的URL模式并在URL中捕获参数。 在接下来的学习中我们将通过实例和代码示例详细介绍React路由的使用方法和原理让你能够熟练地利用React路由构建单页面应用。通过掌握React路由你将能够为用户提供丰富、流畅的页面导航体验同时保持应用的高性能和良好的可维护性。 2. React路由介绍 现代的前端应用大多都是SPA(单页应用程序也就是只有一个HTML页面的应用程序。因为它的用户体验更好、对服务器的压力更小所以更受欢迎。为了有效的使用单个页面来管理原来多页面的功能前端路由应运而生。 前端路由的功能:让用户从一个视图(页面导航到另一个视图页面)前端路由是一套映射规则在React中是URL路径与组件的对应关系使用React路由简单来说就是配置路径和组件配对) 3. React路由的基本使用 3.1 BrowserRouter使用步骤 React路由的基本使用非常简单和直观下面是使用react-router-dom库来创建基本路由的步骤 安装: 通过 yarn 或 npm 安装 react-router-dom 库 yarn add react-router-dom # 或者 npm install react-router-dom导入核心组件: 从 react-router-dom 中导入三个核心组件BrowserRouter也可以重命名为Router、Route和Link。 import { BrowserRouter as Router, Route, Link } from react-router-dom;使用Router组件包裹整个应用: Router组件应当包裹住你的整个应用确保路由的上下文可用于应用的其他部分。 Routerdiv classNameApp{/* ...省略页面内容 */}/div /Router使用Link组件作为导航菜单路由入口: Link组件提供了一个简单的方式来创建导航链接它会渲染为HTML中的a标签。 Link to/first页面一/Link使用Route组件配置路由规则和要展示的组件路由出口: Route组件定义了URL路径与组件之间的映射关系。你可以通过path prop指定URL路径通过component prop指定要渲染的组件。 const First () p页面一的页面内容/p;Routerdiv classNameAppLink to/first页面一/LinkRoute path/first component{First}/Route/div /Router3.2 HashRouter介绍 除了BrowserRouterreact-router-dom库还提供了一个HashRouter组件。HashRouter和BrowserRouter的工作方式略有不同但都能提供基本的路由功能。 HashRouter使用URL的hash部分即#符号后的部分来保持UI和URL的同步。这种方式对于不能提供服务器端渲染支持的静态文件服务器非常有用因为它不需要服务器配置即可提供深层链接。 以下是HashRouter的基本使用方法 import { HashRouter as Router, Route, Link } from react-router-dom;const First () p页面一的页面内容/p;Routerdiv classNameAppLink to/first页面一/LinkRoute path/first component{First}/Route/div /Router在上述代码中我们从react-router-dom导入了HashRouter而不是BrowserRouter并将其重命名为Router以保持代码的简洁和一致。其他的用法和BrowserRouter基本相同只是URL的格式会略有不同例如/first将变为#/first。 4. Route执行过程 React路由的执行过程可以理解为一个按步骤自动触发的序列从用户点击Link组件开始到React路由渲染相应的Route组件。下面是这个过程的详细解释 点击Link组件: 当用户点击Link组件时它会修改浏览器地址栏中的URL。例如如果Link组件的to prop是/first那么点击该Link组件会使浏览器地址栏的URL变为/first。 Link to/first页面一/LinkReact路由监听URL变化: React路由库react-router-dom会监听浏览器地址栏中的URL变化。这个监听过程是通过HTML5 History API或者哈希变化实现的具体取决于你是使用BrowserRouter还是HashRouter。 遍历所有Route组件: 一旦URL发生变化React路由就会开始遍历所有的Route组件检查每个Route组件的path prop与当前的URL的pathname部分是否匹配。 Route path/first component{First}/Route展示匹配的Route组件内容: 如果Route组件的path prop与当前的URL的pathname部分匹配React路由就会渲染该Route组件所指定的component prop。在这个例子中如果URL的pathname是/firstFirst组件就会被渲染到页面上。 const First () p页面一的页面内容/p;这个过程保证了当用户通过导航链接由Link组件提供更改URL时React路由能够正确地渲染与新URL对应的组件。通过这种方式React路由提供了一个简单而强大的方式来构建单页应用程序SPA使开发者能够以一种组织良好、可维护的方式来管理应用的视图和导航逻辑。 5. 编程式导航 在某些场景下我们可能需要通过编程的方式来控制路由的跳转例如在用户登录成功后自动跳转到某个页面。React Router提供了一种编程式导航的方式使得我们能够在JavaScript代码中控制路由的跳转。 场景说明: 假设我们有一个登录页面当用户点击登录按钮并且登录成功后我们想要通过代码将用户重定向到后台首页。 实现编程式导航: React Router为我们提供了history对象它包含了与浏览器历史记录交互的一些方法。我们可以利用history对象的push和go方法来实现编程式导航。 使用history.push方法: history.push方法允许我们导航到一个新的位置以下是如何在登录成功后使用history.push方法跳转到后台首页的示例 import React, { Component } from react; import { withRouter } from react-router-dom;class Login extends Component {handleLogin () {// 假设登录验证逻辑已通过this.props.history.push(/home);};render() {return (divbutton onClick{this.handleLogin}登录/button/div);} }export default withRouter(Login);在上述代码中 我们首先从react-router-dom导入了withRouter高阶组件它会将history对象作为prop传递给Login组件。在handleLogin方法中我们调用了this.props.history.push(/home)来导航到/home路径。用户点击登录按钮后handleLogin方法被调用并将用户导航到后台首页。 使用history.go方法: history.go方法允许我们在浏览器历史记录中前进或后退。参数n表示前进或后退的页面数量。例如n为-1表示后退到上一页 goBack () {this.props.history.go(-1);};在上述方法中我们调用了this.props.history.go(-1)来后退到上一页。类似地我们可以使用n为1来前进到下一页。 通过这种方式React Router的history对象为我们提供了强大而灵活的编程式导航功能使我们能够在代码中精确控制路由的跳转。 6. 默认路由 在React Router中有时我们可能想要为未匹配到的路径提供一个默认的页面通常这个页面是一个“404 Not Found”页面用来告诉用户他们访问了一个不存在的页面。为了实现这个功能我们可以使用Route组件和Switch组件来配置一个默认的路由。 使用Switch和Route实现默认路由 Switch组件是用来包裹一组Route组件的它会从上到下匹配其中的Route一旦找到一个匹配的Route它就会渲染这个Route并忽略其它的Route。如果所有的Route都没有匹配到我们可以在Switch的最后放置一个没有path属性的Route作为默认路由。 以下是一个实现默认路由的示例 import React from react; import { BrowserRouter as Router, Route, Switch } from react-router-dom;const HomePage () divHome Page/div; const AboutPage () divAbout Page/div; const NotFoundPage () div404 Not Found/div;const App () {return (RouterSwitchRoute path/ exact component{HomePage} /Route path/about component{AboutPage} /{/* 默认路由 */}Route component{NotFoundPage} //Switch/Router); };export default App;在上述代码中 我们首先导入了所需的Router, Route和Switch组件。在Switch组件中我们定义了几个具有特定path属性的Route组件。在Switch组件的最后我们添加了一个没有path属性的Route组件并指定了NotFoundPage组件作为它的component属性值。这样当用户访问一个未定义的路由时NotFoundPage组件会被渲染从而展示一个“404 Not Found”页面。 通过这种方式我们可以为React应用配置一个简单而有效的默认路由以处理未匹配到的路径。 7. 匹配模式 React Router的匹配模式可以分为模糊匹配和精确匹配。模糊匹配是默认的匹配模式它允许你在路径中定义一种模式并且任何以该模式开头的路径都会被匹配。这可能会导致多个Route组件被匹配和渲染。为了避免这种情况你可能会想使用精确匹配模式。 7.1 模糊匹配模式 在模糊匹配模式下如果Route组件的path属性值是当前URL路径的前缀那么该Route组件就会被匹配。这种匹配模式允许你创建嵌套路由但是也可能会导致不期望的路由匹配。 例子 import React from react; import { BrowserRouter as Router, Route, Link } from react-router-dom;const Home () divHome Page/div; const Login () divLogin Page/div;const App () {return (RouterdivLink to/loginLogin/Link{/* 模糊匹配 */}Route path/ component{Home} /Route path/login component{Login} //div/Router); };export default App;在上面的例子中当你点击Login链接时你会发现Home组件和Login组件都被渲染了。这是因为/是/login的前缀所以Route path/ component{Home} /被匹配了。 这种模式可能不是你想要的特别是当你有一个默认路由时。为了解决这个问题你可以使用精确匹配模式。 7.2 精确匹配模式 通过为Route组件添加exact属性你可以启用精确匹配模式。在这种模式下只有当path和pathname完全匹配时Route组件才会被匹配。 例子 import React from react; import { BrowserRouter as Router, Route, Link } from react-router-dom;const Home () divHome Page/div; const Login () divLogin Page/div;const App () {return (RouterdivLink to/loginLogin/Link{/* 精确匹配 */}Route path/ exact component{Home} /Route path/login component{Login} //div/Router); };export default App;在上述代码中我们通过添加exact属性到Route path/ component{Home} /确保只有当路径完全是/时Home组件才会被渲染。现在当你点击Login链接时只有Login组件会被渲染。 通过精确匹配模式你可以避免不期望的路由匹配特别是当你有多层路由结构时。所以我们通常会推荐给默认路由添加exact属性。 8.React路由函数的使用 抽象化路由路由表的实现 路由表提供了一个集中的方式来定义应用中所有的路由路径和它们应该如何响应。在React中使用路由表可以使应用结构更加清晰。 创建路由函数 这些函数允许你为你的应用创建自定义路由。 createBrowserRouter: 创建一个使用HTML5 history API的路由器。createMemoryRouter: 创建一个保持路由信息在内存中的路由器通常用于测试和非浏览器环境如React Native。createStaticRouter: 用于在Node环境中渲染静态页面例如服务器端渲染。createHashRouter: 创建一个哈希Api的路由器. 在创建好路由表之后我们可以使用RouterProvider将路由表注入我们的APP内 import {createBrowserRouter, RouterProvider} from react-router-dom const router createBrowserRouter( [{path: /login,element: div登录页/div},{path: /admin,element: div管理页/div} ])const root ReactDOM.createRoot(document.getElementById(root)); root.render(RouterProvider router{router}/RouterProvider )路由导航跳转 路由系统中的多个路由之间需要进行路由跳转并且在跳转的同时有可能需要传递参数进行通信。 声明式导航 声明式导航是指通过在模版中通过**Link/组件描述出要跳转到哪里去**比如后台管理系统的左侧菜单通常使用这种方式进行。 语法说明:通过给组件的to属性指定要跳转到路由path组件会被渲染为浏览器支持的a链接如果需要传参直接通过字符串拼接的方式拼接参数即可。 Link to/article文章/Link编程式导航命令化导航 编程式导航是指通过useNavigate钩子得到导航方法然后通过调用方法以命令式的形式进行路由跳转比如想在登录请求完毕之后跳转就可以选择这种方式更加灵活。 import {useNavigate} from react-router-domconst App() {const navigate useNavigate();return (div我是登录页button onClick{()navigate(/article)}跳转文章/button/div) }语法说明通过调用navigate方法传入地址path实现跳转. 路由导航跳转传参 searchParams传参 我们在navigate函数里在传入路由的路径时可以直接写入参数也可以直接传入参数并使用searchParams就可以进行使用了。 // 直接声明参数 const id 1001 const name user navigate(/artical?id${id}name${name})在searchParams里使用传入的参数使用get方法获取 const [params] searchParams() const id params.get(id)useParams传参 同样在navigate函数内我们还可以使用useParams进行接收参数接受到的参数是一个参数对象 const params useParams() const id params.id但是在使用useParams传参之前我们需要修改路由表的配置我们需要用占位符来让路由器知道我们这个路由将要传入对应的参数。 const router createBrowserRouter( [{path: /login,element: div登录页/div},{path: /admin,element: div管理页/div},{path: /article/:id,element: div文章页/div} ])useLocation传参 在useLocation传参过程中可以不需要路由表的配合但是我们需要在Link /中传入state参数。并在对应的路由组件内获取参数。 Link to/home state{{id:id, title:title, content:content}}我是Link/Link在对应的路由组件内获取对应的参数 const Home() {const {state:{id, title, content}} useLocation();return (divp{id}/pp{title}/pp{content}/p/div) }嵌套路由实现 实现步骤: 使用children属性配置路由嵌套关系 使用Outletl组件配置二级路由渲染位置 首先我们需要在路由表内声明当前路由下存在子路由并声明路由组件 const router createBrowserRouter( [{path: /,element: div我是主页/divchildren: [ // 使用children值来声明子路由{path: home,element: div我是主页的home/div},{path: about,element: About /}]}{path: /login,element: div登录页/div},{path: /admin,element: div管理页/div}, ])在路由组件之下我们要使用Outletl表示二级路由的渲染位置 const layout() {return (divdiv我是layout/divLink to/home主页/LinkLink to/about关于页/Link{/*二级路由渲染位置*/}Outlet //div) }嵌套路由的默认二级路由的配置 当访问的是一级路由时默认的二级路由组件可以得到渲染只需要在二级路由的位置去掉path设置index属性为true。 比如我们想进入/路由之后自动进入他的二级路由里的home路由内这个时候我们只需要把他的path去掉设置index属性为true即可。 const router createBrowserRouter( [{path: /,element: div我是主页/divchildren: [ // 使用children值来声明子路由{index: true,element: div我是主页的home/div},{path: about,element: About/About}]}{path: /login,element: div登录页/div},{path: /admin,element: div管理页/div}, ])404路由导航的实现 404路由 场景∶当浏览器输入url的路径在整个路由配置中都找不到对应的path为了用户体验可以使用404兜底组件进行渲染 实现步骤: 准备一个NotFound组件 在路由表数组的末尾以*号作为路由path配置路由。 const router createBrowserRouter( [{path: /,element: div我是主页/divchildren: [ // 使用children值来声明子路由{index: true,element: div我是主页的home/div},{path: about,element: About/About}]}{path: /login,element: div登录页/div},{path: /admin,element: div管理页/div},{path: *,element: NotFonud /} ])9. React路由总结 React路由是React应用中处理路由即页面导航的核心机制它允许我们构建单页应用SPA在单个页面中展现多个视图而无需重新加载整个页面。以下是对前面讨论内容的简单总结以及对React路由基础的进一步阐述 单页应用SPA与React路由 React路由通过管理多个视图组件来实现SPA的效果它提供了一种方式来定义不同的URL路径与不同的React组件之间的映射关系。 核心组件 Router: 该组件负责包裹整个应用创建一个路由上下文使得其他路由相关的组件可以正确地工作。通常情况下Router组件只需要在应用的最外层使用一次。Link: 该组件允许用户通过点击链接来导航到不同的页面。它是路由的入口。Route: 该组件负责根据当前的URL路径来决定是否渲染对应的组件。它是路由的出口。 编程式导航 通过props.history对象我们可以在JavaScript代码中直接控制路由的行为例如导航到一个新页面。 匹配模式 默认情况下React路由使用模糊匹配模式只要pathname以path开头就认为匹配成功。这种模式在某些情况下可能会导致意外的匹配结果。为了更精确地控制匹配行为可以通过给Route组件添加exact属性来启用精确匹配模式。在精确匹配模式下只有当pathname和path完全相等时才认为匹配成功。 组件化的路由 React路由的设计理念是“一切皆组件”即路由本身也是通过组件来实现的。这种设计使得React路由非常灵活和易于理解你可以像思考React组件一样来思考React路由。 通过理解和应用以上几点你可以构建出具有良好导航结构和用户体验的React应用。同时React路由的组件化设计也使得路由的扩展和自定义变得非常简单和直观。 Redux的概述与使用 Redux的概述 1.1 什么是 Redux Redux 是一个用于JavaScript的状态容器它提供可预测化的状态管理能力。通过Redux你可以构建出具有一致性的应用这些应用可以运行在不同的环境如客户端、服务器、原生应用中并且非常容易进行测试。Redux不仅限于React也可以与其他UI库如Angular、Vue等一起使用。Redux与React没有直接关联如同Java与JavaScript并不是一个同门语言一般但是Redux最多的使用场景就是与React共同合作管理全局组件的状态。 1.2 Redux的设计初衷 随着JavaScript单页面应用SPA的开发变得日益复杂需要管理更多的state包括但不限于服务器响应、缓存数据、本地生成尚未持久化到服务器的数据以及UI状态。如果不妥善管理这些状态可能会相互影响导致应用的行为难以预测。例如一个模型model的变化可能会影响到另一个模型而视图view的变化可能会进一步影响到模型从而可能引发另一个视图的变化。Redux的出现旨在通过引入严格的状态管理规则解决这种复杂状态间的依赖和影响问题使得状态的变化变得可预测和可控。 1.3 Redux的三大核心原则 单一数据源: 整个应用的 state 被储存在一颗 object tree 中这个 object tree 只存在于唯一一个 store 中。这样做不仅使得应用的状态结构变得清晰、一目了然同时也便于调试和状态的持久化。(在这里你可以使用Mermaid流程图来绘制和解释React中每个组件如何维护自己的状态以及如何将整个应用的状态储存在一个唯一的store中的object tree。) State 是只读的: 唯一改变 state 的方式是通过触发 action。action 是一个描述事件的对象它通常包含一个type属性来指示这个 action 的类型以及其他一些数据。这样做确保了视图和网络请求不能直接修改state而只能通过分发dispatchaction来表达修改意图。所有的修改都被集中处理并且严格按照一个接一个的顺序执行。 store.dispatch({ type: COMPLETE_TODO, index: 1 });使用纯函数来执行修改: Reducers 是用于描述如何根据 action 更新 state 的纯函数。它们接收先前的 state 和一个 action然后返回新的 state。Reducers 的纯函数特性使得它们易于测试、易于组合和重用。同时它们也可以被用于实现时间旅行调试、状态持久化等高级功能。 1.4 Redux概述总结: Redux 是一个 JavaScript 状态容器库: 可预测: 通过单一数据源和纯函数的使用Redux使得状态的变化变得可预测和一致。每次发出一个动作action都会通过一个纯函数reducer来更新状态从而确保相同的输入始终会得到相同的输出。一致: 不管是在客户端、服务器还是原生环境中Redux的行为都是一致的使得它非常适合构建跨平台的应用。透明: 通过Redux DevTools开发者可以实时地观察到状态的变化以及每一个动作如何影响应用的状态。这种透明度使得调试和理解应用的行为变得更为简单。 Redux 的三大核心原则: 单一数据源: 所有的状态都存储在一个JavaScript对象中这使得它更容易管理也更容易调试和检查。这个对象也是序列化的所以可以方便地持久化到本地存储或服务器。单一的状态树也使得实现如时间旅行、状态持久化或者服务器渲染等功能变得可能和相对容易。 State 是只读的: 这个原则保证了状态的不可变性即状态是不可以直接被修改的唯一改变状态的方式是通过触发action。这种方式提供了一种清晰、一致的方法来修改状态并且也使得状态的变化变得可追踪和可预测。 使用纯函数来执行修改: Reducers是纯函数它们不会产生任何副作用也不依赖外部的状态或变量。它们只依赖于传入的参数并且总是会返回一个新的状态对象。这种纯函数的特性使得它们非常容易测试并且也可以通过组合不同的reducers来构建复杂的应用逻辑。 通过这些核心原则Redux提供了一个可靠且强大的状态管理解决方案它可以帮助开发者构建复杂、可维护和可扩展的应用。 你已经很好地概述了 Redux 的组成部分和它们的功能。让我们为每个部分提供更多细节和清晰度。 Redux组成 2.1 State - 状态: State 是应用的状态树它包含了应用的数据和UI状态。在React项目中通常可以将 State 分为三类: Domain Data: 通常来自服务器端的数据例如用户信息、商品列表等。UI State: 决定当前UI展示的状态例如弹框的显示隐藏、受控组件的状态等。App State: App级别的状态例如当前是否显示加载中、当前路由信息等通常这些状态可能会被多个组件共享和使用。 2.2 Action - 事件: Actions是发送数据到store的载体。它们是描述“发生了什么”的对象通常通过store.dispatch()方法发送到store。 Action特点: Action 本质上是一个 JavaScript 对象。必须包含一个 type 属性来表示要执行的动作多数情况下type 会被定义成字符串常量。除 type 字段外action 对象的结构是自由的可以根据需要添加其他属性。Action 创建函数是创建 action 的函数它描述了有事情要发生但并没有描述如何更新 state。 基本结构: 一个Action是一个简单的JavaScript对象它至少包含一个type属性通常还包含一些数据。 {type: ADD_TODO,text: Learn Redux }Action创建函数: 这些函数返回actions它们是创建action的唯一方式使得代码更清晰也更容易测试。 function addTodo(text) {return {type: ADD_TODO,text}; }序列图详解 #mermaid-svg-EcDEhLeVqyNSVTKG {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-EcDEhLeVqyNSVTKG .error-icon{fill:#552222;}#mermaid-svg-EcDEhLeVqyNSVTKG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EcDEhLeVqyNSVTKG .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-EcDEhLeVqyNSVTKG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EcDEhLeVqyNSVTKG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EcDEhLeVqyNSVTKG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EcDEhLeVqyNSVTKG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EcDEhLeVqyNSVTKG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EcDEhLeVqyNSVTKG .marker.cross{stroke:#333333;}#mermaid-svg-EcDEhLeVqyNSVTKG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EcDEhLeVqyNSVTKG .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EcDEhLeVqyNSVTKG text.actortspan{fill:black;stroke:none;}#mermaid-svg-EcDEhLeVqyNSVTKG .actor-line{stroke:grey;}#mermaid-svg-EcDEhLeVqyNSVTKG .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-EcDEhLeVqyNSVTKG .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-EcDEhLeVqyNSVTKG #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-EcDEhLeVqyNSVTKG .sequenceNumber{fill:white;}#mermaid-svg-EcDEhLeVqyNSVTKG #sequencenumber{fill:#333;}#mermaid-svg-EcDEhLeVqyNSVTKG #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-EcDEhLeVqyNSVTKG .messageText{fill:#333;stroke:#333;}#mermaid-svg-EcDEhLeVqyNSVTKG .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EcDEhLeVqyNSVTKG .labelText,#mermaid-svg-EcDEhLeVqyNSVTKG .labelTexttspan{fill:black;stroke:none;}#mermaid-svg-EcDEhLeVqyNSVTKG .loopText,#mermaid-svg-EcDEhLeVqyNSVTKG .loopTexttspan{fill:black;stroke:none;}#mermaid-svg-EcDEhLeVqyNSVTKG .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-EcDEhLeVqyNSVTKG .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-EcDEhLeVqyNSVTKG .noteText,#mermaid-svg-EcDEhLeVqyNSVTKG .noteTexttspan{fill:black;stroke:none;}#mermaid-svg-EcDEhLeVqyNSVTKG .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EcDEhLeVqyNSVTKG .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EcDEhLeVqyNSVTKG .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EcDEhLeVqyNSVTKG .actorPopupMenu{position:absolute;}#mermaid-svg-EcDEhLeVqyNSVTKG .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-EcDEhLeVqyNSVTKG .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EcDEhLeVqyNSVTKG .actor-man circle,#mermaid-svg-EcDEhLeVqyNSVTKG line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-EcDEhLeVqyNSVTKG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Component Store store.dispatch(action) 发送一个action 更新状态重新渲染组件 Component Store 在这个序列图中: 组件 (Component) 调用 store.dispatch(action) 方法来发送一个 Action 到 Store。Store 调用 Reducer传递当前的 State 和 Action 作为参数。Reducer 返回一个新的 State 到 Store。Store 更新 State然后重新渲染相关的组件。 这个流程图简明地展示了在Redux中如何通过store.dispatch()方法发送一个Action并通过Reducer来更新State最终达到更新应用UI的目的。 2.3 Reducer: Reducer 是一个函数它响应发送过来的 actions并返回新的 state。 Reducers指定了如何根据actions更新state。它们是纯函数接收先前的state和一个action并返回新的state。 基本结构: function todoApp(state initialState, action) {switch (action.type) {case ADD_TODO:// ...省略default:return state;} }Reducer特点: Reducer 函数接收两个参数: 第一个参数是当前的 state第二个参数是 action。必须返回一个新的 state或者在没有变化时返回原始的 state。Reducer 是纯函数不应产生任何副作用。 分割Reducers: 为了管理大型应用的复杂状态通常将一个大的reducer分割成多个小的reducers每个管理state的一部分然后使用combineReducers将它们组合在一起。 #mermaid-svg-HdGyDg3X0GCU66Sb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-HdGyDg3X0GCU66Sb .error-icon{fill:#552222;}#mermaid-svg-HdGyDg3X0GCU66Sb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HdGyDg3X0GCU66Sb .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-HdGyDg3X0GCU66Sb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HdGyDg3X0GCU66Sb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HdGyDg3X0GCU66Sb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HdGyDg3X0GCU66Sb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HdGyDg3X0GCU66Sb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HdGyDg3X0GCU66Sb .marker.cross{stroke:#333333;}#mermaid-svg-HdGyDg3X0GCU66Sb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HdGyDg3X0GCU66Sb .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HdGyDg3X0GCU66Sb text.actortspan{fill:black;stroke:none;}#mermaid-svg-HdGyDg3X0GCU66Sb .actor-line{stroke:grey;}#mermaid-svg-HdGyDg3X0GCU66Sb .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-HdGyDg3X0GCU66Sb .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-HdGyDg3X0GCU66Sb #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-HdGyDg3X0GCU66Sb .sequenceNumber{fill:white;}#mermaid-svg-HdGyDg3X0GCU66Sb #sequencenumber{fill:#333;}#mermaid-svg-HdGyDg3X0GCU66Sb #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-HdGyDg3X0GCU66Sb .messageText{fill:#333;stroke:#333;}#mermaid-svg-HdGyDg3X0GCU66Sb .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HdGyDg3X0GCU66Sb .labelText,#mermaid-svg-HdGyDg3X0GCU66Sb .labelTexttspan{fill:black;stroke:none;}#mermaid-svg-HdGyDg3X0GCU66Sb .loopText,#mermaid-svg-HdGyDg3X0GCU66Sb .loopTexttspan{fill:black;stroke:none;}#mermaid-svg-HdGyDg3X0GCU66Sb .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-HdGyDg3X0GCU66Sb .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-HdGyDg3X0GCU66Sb .noteText,#mermaid-svg-HdGyDg3X0GCU66Sb .noteTexttspan{fill:black;stroke:none;}#mermaid-svg-HdGyDg3X0GCU66Sb .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HdGyDg3X0GCU66Sb .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HdGyDg3X0GCU66Sb .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HdGyDg3X0GCU66Sb .actorPopupMenu{position:absolute;}#mermaid-svg-HdGyDg3X0GCU66Sb .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-HdGyDg3X0GCU66Sb .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HdGyDg3X0GCU66Sb .actor-man circle,#mermaid-svg-HdGyDg3X0GCU66Sb line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-HdGyDg3X0GCU66Sb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Component Store Reducer store.dispatch(action) Action 描述了 发生了什么 Store 调用 Reducer Reducer 是纯函数接收先前的 state 和 action 返回新状态 更新状态重新渲染组件 Component Store Reducer 序列图详解 在这个序列图中: 组件 (Component) 通过调用 store.dispatch(action) 方法发送一个 动作 (Action) 到 存储库 (Store)其中 Action 描述了“发生了什么”。存储库 (Store) 随后调用 Reducer传递当前的 状态 (State) 和 动作 (Action) 作为参数。Reducer 是一个纯函数它根据接收到的 状态 (State) 和 动作 (Action) 计算并返回一个新的 状态 (State)。 Reducer 返回新的 状态 (State) 到 存储库 (Store)随后 存储库 (Store) 更新 状态 (State)。最终存储库 (Store) 更新了 状态 (State) 后通知 组件 (Component) 重新渲染以反映状态的变化。 2.4 Store: Store 是 Redux 的核心它将 action 和 reducer 联系到一起同时维护应用的 state。 Store特点: 提供 getState() 方法获取 state。提供 dispatch() 方法发送 action。提供 subscribe() 方法注册监听器监听 state 的变化。subscribe() 返回一个函数用于注销监听器。通过 createStore() 方法创建 store传递 reducer 作为参数。 import { createStore } from redux; import todoApp from ./reducers; const store createStore(todoApp);2.5 Redux组成总结: State: 应用的数据和UI状态可以分为 Domain Data, UI State, 和 App State.Action: 描述事件的对象是改变 state 的唯一方式但不直接修改state主要用来描述即将要发生什么。Reducer: 纯函数根据 action 更新并返回新的 state。Store: Redux的核心连接 action 和 reducer同时维护应用的 state提供了一些方法来操作和监听 state。 通过理解 Redux 的这些组成部分以及它们的作用和交互方式你将能够更好地理解和使用 Redux 来管理你的应用状态。 Redux快速安装开始 创建一个 React Redux 项目涉及多个步骤。以下是从安装 Redux 到创建 Redux 文件夹的详细步骤。 1. 创建一个新的React项目: 首先你需要创建一个新的React项目如果你还没有一个的话。 npx create-react-app my-redux-app cd my-redux-app2. 安装 Redux 和 React-Redux: 你需要安装 Redux 和 React-ReduxReact-Redux 是连接 React 和 Redux 的官方库。 npm install redux react-redux3. 创建 Redux 文件夹: 在你的项目根目录下创建一个名为 redux 的文件夹。这个文件夹将包含你所有的 Redux 相关代码例如reducers, actions, 和 middleware。 mkdir src/redux cd src/redux4. 创建 Action 和 Reducer 文件: 创建Action文件夹 在 redux 文件夹中创建一个名为 actions 的文件夹并在该文件夹中创建你的 action 文件。例如你可以创建一个名为 index.js 的文件来存储你的 actions。 mkdir actions touch actions/index.js在actions文件里的代码文件里创建一个action函数里面返回一个action对象。注意action对象必须要有type属性 const sendAction () {// 返回一个action对象return {type : send_action_type,value: 发送了一个action} }把这个action创建的函数导出 module.exports {sendAction }Reducers: 在 redux 文件夹中创建一个名为 reducers 的文件夹并在该文件夹中创建你的 reducer 文件。例如你可以创建一个名为 index.js 的文件来组合和导出你的 reducers。 mkdir reducers touch reducers/index.js创建一个reducer函数注意reducer需要接受两个参数state和action。 const rootReducer (state, action) {// to do somethings. }第一个参数是默认状态我们可以定义一个初始化的state然后进行赋值 const initState {value : default} const rootReducer (state initState, action) {// to do somethings. }在函数里面判断第二个参数action的type值是否是我们发送的 如果是的话我们可以通过return返回新的state。 const initState {value : default} const rootReducer (state initState, action) {switch (action){case send_type:return Object.assign({/*new state object*/}, state, action);default:return state} }把reducer进行导出 const initState {value : default} const rootReducer (state initState, action) {switch (action){case send_type:return Object.assign({/*new state object*/}, state, action);default:return state} } module.exports {rootReducer }5. 创建 Store: 在 redux 文件夹中创建一个名为 store.js 的文件用于创建和导出你的 Redux store。 touch store.js在 store.js 文件中你将导入 createStore 函数和你的 root reducer然后使用它们来创建你的 store。 import { createStore } from redux; import rootReducer from ./reducers;const store createStore(rootReducer );export default store;6. 连接 Redux 到你的 React 应用: 给页面的button按钮绑定一个点击事件在组件一加载完毕的时候我们通过store来进行监听器的注册返回值可以用来注销监听 this.unSubbscribe store.subscribe(() {...} );在点击事件处理函数中通过store.dispatch来发送一个action. handleClick () {store.dispath(sendAction()) }React-redux的使用与入门 React-Redux 简介 React-Redux 是 Redux 的官方 React 绑定库它允许你轻松地在 React 应用中集成和使用 Redux。通过 React-Redux你可以让你的 React 组件连接到 Redux Store共享和管理全局状态。React-Redux 提供了一些 API 和工具来简化在 React 中使用 Redux 的过程。 下面是 React-Redux 的一些主要特点和组成部分 Provider 组件: Provider 是一个 React 组件它使得 Redux Store 可以在你的 React 应用中的任何地方被访问。你只需将 Provider 组件包裹在你的应用的根组件周围并将你的 Redux Store 传递给它。 import React from react; import ReactDOM from react-dom; import { Provider } from react-redux; import store from ./redux/store; import App from ./App;ReactDOM.render(Provider store{store}App //Provider,document.getElementById(root) );connect 函数: connect 函数是一个高阶函数它返回一个新的连接到 Redux Store 的 React 组件。它接受两个参数 mapStateToProps 和 mapDispatchToProps分别用于将 Redux Store 中的状态和 dispatch 方法映射到你的 React 组件的 props。 import { connect } from react-redux;const mapStateToProps state ({// map state to props });const mapDispatchToProps dispatch ({// map dispatch to props });export default connect(mapStateToProps, mapDispatchToProps)(YourComponent);useDispatch 和 useSelector 钩子: 在函数组件中你可以使用 useDispatch 和 useSelector 钩子来分别获取 dispatch 函数和选择 Redux Store 中的状态。 import React from react; import { useDispatch, useSelector } from react-redux;function YourComponent() {const dispatch useDispatch();const state useSelector(state state);// ... }创建切片 (Slice): React-Redux 鼓励使用切片 (Slice) 模式来组织你的 actions 和 reducers。一个切片包含了它自己的 actions、reducers 和初始状态使得代码更加模块化和易于管理。 React-Redux 不仅为你提供了一种在 React 中使用 Redux 的简单方法还提供了性能优化和其他实用功能以确保你的应用运行得更加顺畅。通过使用 React-Redux你可以构建出结构清晰、可维护和可扩展的 React 应用。 React-redux基本使用 React-Redux 是官方提供的 Redux 和 React 的绑定库。它使你能够将 Redux 的状态和 dispatch 方法映射到 React 组件的 props 中。使用 React-Redux你可以轻松地在 React 应用中集成 Redux。 下面是 React-Redux 的基本使用步骤 安装依赖: 在开始之前确保你已经安装了 react-redux 和 redux。 npm install redux react-redux文件架构为了更好管理redux项目内容通常会在src文件夹下的创建一个redux文件夹里面分别存放store\action\reducer的代码进行存放。 编写React-redux代码 创建 Redux Actions: Actions 是描述发生了什么的对象也就是描述事件对象它们通常通过 dispatch 函数发送到 store。 // src/redux/actions.js export const increment () ({type: INCREMENT });export const decrement () ({type: DECREMENT });创建 Redux Reducers: Reducers 是纯函数它们接受先前的状态和动作并返回新的状态。 // src/redux/reducers/index.js import { combineReducers } from redux;const initialState {count: 0 };function counterReducer(state initialState, action) {switch (action.type) {case INCREMENT:return {...state,count: state.count 1};case DECREMENT:return {...state,count: state.count - 1};default:return state;} }const rootReducer combineReducers({counter: counterReducer });export default rootReducer;创建 Redux Store: 首先你需要创建一个 Redux Store 来保存应用的状态。 // src/redux/store.js import { createStore } from redux; import rootReducer from ./reducers;const store createStore(rootReducer);export default store;在 React 组件中使用 React-Redux: 现在你可以在 React 组件中使用 connect 函数将 Redux 的 state 和 dispatch 方法映射到组件的 props 中。 // src/components/Counter.js import React from react; import { connect } from react-redux; import { increment, decrement } from ../redux/actions;function Counter({ count, increment, decrement }) {return (divbutton onClick{decrement}-/buttonspan{count}/spanbutton onClick{increment}/button/div); }const mapStateToProps state ({count: state.counter.count });const mapDispatchToProps {increment,decrement };export default connect(mapStateToProps, mapDispatchToProps)(Counter);使用 Provider 包装应用: 最后使用 react-redux 的 Provider 组件将你的应用包装在 Redux store 之中。Provider包裹下的所有react组件都会被传递同一个store以此进行组件数据对象的使用。 // src/index.js import React from react; import ReactDOM from react-dom; import { Provider } from react-redux; import store from ./redux/store; import Counter from ./components/Counter;ReactDOM.render(Provider store{store}Counter //Provider,document.getElementById(root) );通过以上步骤你应该已经成功地在你的 React 应用中集成了 Redux 和 React-Redux。现在你可以在组件中通过 props 访问 Redux 的状态和 dispatch 方法并能够轻松地管理和更新应用的状态。 react-toolkit的介绍与基本使用 React Toolkit (RTK) 是官方推荐的用于构建 Redux 应用程序的标准方法。它旨在简化 Redux 代码的编写和维护并提供了许多有用的实用程序和中间件以帮助开发人员更快更容易地构建复杂的应用程序。简单来说React Toolkit是一套工具的集合意在简化在React中编写redux逻辑的过程通过一个函数传入对应的参数使得RTK帮你完成生成action和action type也简化store创建的过程以此实现简化书写方式。 安装: 你可以通过 npm 或 yarn 安装 React Toolkit。 npm install reduxjs/toolkit react-redux # 需要安装好react-redux # 或 yarn管理包工具 yarn add reduxjs/toolkit react-redux # 需要安装好react-reduxReact-toolkit基本使用代码 使用React-Toolkit能够减少我们大量的逻辑编码的过程。 例如我们要使用react toolkit创建一个计数器我们可以这样配置和创建我们的counterStore counterStore.js import { createSlice } import reduxjs/toolkitconst counterStore createSlice({name : counter, // 初始化状态数据initialState: {count: 0}// 修改数据的同步方法reducers: {inscrement(state){state.count;},decrement(state){state.count--;}} })// 解构出创建的action对象函数 {actionCreater} const {inscrement, decrement} counterStore.actions // 获取reducer函数 const counterReducer counterStore.reducer // 导出创建action对象的函数和reducer函数 export {inscrement, decrement} export default counterReducer使用对象src/store/index.js import { configureStore } from reduxjs/toolkit // 导入子模块reducer import counterReducer from ./modules/counterStore// 创建根store组合的子模块 const store configureStore({reducer: {counter: counterReducer} })export default store为React注入store react-redux负责把Redux和React链接起来内置Provider组件通过store参数把创建好的store实例注入到应用中链接正式建立。 App.js import { Provider } from react-redux import store from ./store const root ReactDOM.createRoot(document.getElementById(root)) root.render(Provider store{store}App /Provider )React组件使用store中的数据 在React组件中使用store中的数据需要用到一个钩子函数: useSelector它的作用是把store中的数据映射到组件中使用样例如下: const {count} useSelector(state state.counter)这里的state.counter是来自于src/store/index.js下的部分 const store configureStore({reducer: {counter: counterReducer // state.counter来自于这里} })pages/counter.js import {useSelector} from react-reduxfunction App(){const {count} useSelector(state state.counter)return (div classNameApp{count}/div) } export default AppReact组件修改store中的数据 React组件中修改store中的数据需要借助另外一个hook函数– useDispatch它的作用是生成提交action对象的dispatch函数使用样例如下: pages/counter.js import {useSelector} from react-redux // 导入之前创建的actionCreator import {inscrement, decrement} from ./store/modules/counterStore function App(){const {count} useSelector(state state.counter)const dispath useDispatch()return (div classNameAppbutton onClick{() dispatch(decreament())}-/button{count}button onClick{() dispatch(inscrement())}/button/div) } export default App总结 组件中使用哪个hook函数获取store中的数据? useSelector 组件中使用哪个hook函数获取dispatch方法? useDispatch 如何得到要提交action对象? 执行store模块中导出的actionCreater方法 React-toolkit异步状态处理 在RTK里的异步状态处理的逻辑一般如下 创建store的写法保持不变配置好同步修改状态的方法 单独封装一个函数在函数内部return一个新函数在新函数中 封装异步请求获取数据调用同步actionCreator传入异步数据生成一个action对象并使用dispatch提交 组件中dispatch的写法保持不变。 完整编码 store/modules/channelList.js import {createSlice} from reduxjs/toolkit// 步骤1: 创建store的写法保持不变配置好同步修改状态的方法 createSlice({name: channel,initialState: {channelList: []},reducers: {setChannels(state, action){state.channelList action.payload}} })// 异步请求 const {setChannels} channelStore.actions // 步骤2: 单独封装一个函数在函数内部return一个新函数 const fetchChannelList () {return (dispatch) { // 在新函数中// 封装异步请求获取数据const resultList [{id:1, name:caixy},{id:2, name:caixypromise},{id:3, name:CAIXYPROMISE}]// 调用同步actionCreator传入异步数据生成一个action对象并使用dispatch提交dispatch(setChannels(resultList))} }export {fetchChannelList} const reducer channelStore.reducer export default reducer;src/App.js import {useSelector, useDispatch} from react-redux function App() {const {channelList} useSelector(state state.channel)const dispatch useDispatch()//使用useEffect触发异步执行useEffect(() {dispatch(fetchChannelList())}, [dispatch])// 利用dispatch不可变的规则保证组件第一次渲染时执行。避免了每次组件渲染时都发送请求return (div classNameAppul{channelList.map(item li key{item.id}{item.name}/li)}/ul/div) }在这段代码中useEffect 的使用是为了确保 dispatch(fetchChannelList()) 只在组件第一次渲染时执行而不是在每次渲染时执行。如果不使用 useEffectdispatch(fetchChannelList()) 会在每次组件渲染时执行可能会导致不必要的重复请求和渲染。 dispatch 是 Redux 提供的一个函数它通常是不可变的。在 useEffect 的依赖项数组中包含 dispatch能确保 useEffect 中的代码只在组件第一次渲染时执行而不是在每次渲染时执行。这样做可以减少不必要的请求和操作提高应用的性能。 通过设置 useEffect 的依赖项数组为 [dispatch]你告诉 React 只有当 dispatch 函数发生变化时才重新执行 useEffect 中的代码。但由于 dispatch 函数通常不会变化所以实际上 useEffect 中的代码只会在组件第一次渲染时执行。这种做法避免了每次组件渲染时都发送请求节省了网络资源提高了应用的性能。 r.net/gh/CaixyPromise/Blog_Imagemain/img/202310241623879.png alt“image-20231024162250503” style“zoom:80%;” / 例如我们要使用react toolkit创建一个计数器我们可以这样配置和创建我们的counterStore counterStore.js import { createSlice } import reduxjs/toolkitconst counterStore createSlice({name : counter, // 初始化状态数据initialState: {count: 0}// 修改数据的同步方法reducers: {inscrement(state){state.count;},decrement(state){state.count--;}} })// 解构出创建的action对象函数 {actionCreater} const {inscrement, decrement} counterStore.actions // 获取reducer函数 const counterReducer counterStore.reducer // 导出创建action对象的函数和reducer函数 export {inscrement, decrement} export default counterReducer使用对象src/store/index.js import { configureStore } from reduxjs/toolkit // 导入子模块reducer import counterReducer from ./modules/counterStore// 创建根store组合的子模块 const store configureStore({reducer: {counter: counterReducer} })export default store为React注入store react-redux负责把Redux和React链接起来内置Provider组件通过store参数把创建好的store实例注入到应用中链接正式建立。 App.js import { Provider } from react-redux import store from ./store const root ReactDOM.createRoot(document.getElementById(root)) root.render(Provider store{store}App /Provider )React组件使用store中的数据 在React组件中使用store中的数据需要用到一个钩子函数: useSelector它的作用是把store中的数据映射到组件中使用样例如下: const {count} useSelector(state state.counter)这里的state.counter是来自于src/store/index.js下的部分 const store configureStore({reducer: {counter: counterReducer // state.counter来自于这里} })pages/counter.js import {useSelector} from react-reduxfunction App(){const {count} useSelector(state state.counter)return (div classNameApp{count}/div) } export default AppReact组件修改store中的数据 React组件中修改store中的数据需要借助另外一个hook函数– useDispatch它的作用是生成提交action对象的dispatch函数使用样例如下: pages/counter.js import {useSelector} from react-redux // 导入之前创建的actionCreator import {inscrement, decrement} from ./store/modules/counterStore function App(){const {count} useSelector(state state.counter)const dispath useDispatch()return (div classNameAppbutton onClick{() dispatch(decreament())}-/button{count}button onClick{() dispatch(inscrement())}/button/div) } export default App总结 组件中使用哪个hook函数获取store中的数据? useSelector 组件中使用哪个hook函数获取dispatch方法? useDispatch 如何得到要提交action对象? 执行store模块中导出的actionCreater方法 React-toolkit异步状态处理 在RTK里的异步状态处理的逻辑一般如下 创建store的写法保持不变配置好同步修改状态的方法 单独封装一个函数在函数内部return一个新函数在新函数中 封装异步请求获取数据调用同步actionCreator传入异步数据生成一个action对象并使用dispatch提交 组件中dispatch的写法保持不变。 完整编码 store/modules/channelList.js import {createSlice} from reduxjs/toolkit// 步骤1: 创建store的写法保持不变配置好同步修改状态的方法 createSlice({name: channel,initialState: {channelList: []},reducers: {setChannels(state, action){state.channelList action.payload}} })// 异步请求 const {setChannels} channelStore.actions // 步骤2: 单独封装一个函数在函数内部return一个新函数 const fetchChannelList () {return (dispatch) { // 在新函数中// 封装异步请求获取数据const resultList [{id:1, name:caixy},{id:2, name:caixypromise},{id:3, name:CAIXYPROMISE}]// 调用同步actionCreator传入异步数据生成一个action对象并使用dispatch提交dispatch(setChannels(resultList))} }export {fetchChannelList} const reducer channelStore.reducer export default reducer;src/App.js import {useSelector, useDispatch} from react-redux function App() {const {channelList} useSelector(state state.channel)const dispatch useDispatch()//使用useEffect触发异步执行useEffect(() {dispatch(fetchChannelList())}, [dispatch])// 利用dispatch不可变的规则保证组件第一次渲染时执行。避免了每次组件渲染时都发送请求return (div classNameAppul{channelList.map(item li key{item.id}{item.name}/li)}/ul/div) }在这段代码中useEffect 的使用是为了确保 dispatch(fetchChannelList()) 只在组件第一次渲染时执行而不是在每次渲染时执行。如果不使用 useEffectdispatch(fetchChannelList()) 会在每次组件渲染时执行可能会导致不必要的重复请求和渲染。 dispatch 是 Redux 提供的一个函数它通常是不可变的。在 useEffect 的依赖项数组中包含 dispatch能确保 useEffect 中的代码只在组件第一次渲染时执行而不是在每次渲染时执行。这样做可以减少不必要的请求和操作提高应用的性能。 通过设置 useEffect 的依赖项数组为 [dispatch]你告诉 React 只有当 dispatch 函数发生变化时才重新执行 useEffect 中的代码。但由于 dispatch 函数通常不会变化所以实际上 useEffect 中的代码只会在组件第一次渲染时执行。这种做法避免了每次组件渲染时都发送请求节省了网络资源提高了应用的性能。
http://www.yutouwan.com/news/142585/

相关文章:

  • 如何做后台网站的教程网站添加视频
  • 网站建设中html网页个人导航网站怎么备案
  • 无锡网站制作公司网片加工机器
  • wordpress文章半透明福州seo建站
  • 淘宝搜索热词排名seo标题优化
  • dede网站logo怎么改锦州市网站建设
  • 免费建设论坛网站做招聘网站的需求分析
  • 热门搜索关键词怎样优化网站自然排名
  • 用asp做旅游网站建筑工程发布网站
  • 汕头网站开发定制大理住房和城乡建设局网站
  • dedecms确定网站风格网站建设 中企动力 常州
  • 建设招标项目常挂网站有哪些网站的简介怎么在后台炒做
  • xxx网站策划书线上引流的八种推广方式
  • 自己做网站写文章如何增加网站的权重
  • 网站有效内容的宣传及推广如何做跨境电商怎么做
  • 一家网站建设公司需要什么资质移动商城网站建设 深圳
  • 一个空间怎么做多个网站长沙广告传媒有限公司
  • 手机网站建设在哪儿深圳市绿色建筑信息平台
  • 想给公司做个网站怎么做的提高网站知名度
  • 推广引流图片临沂网站优化哪家好
  • 怎样免费注册自己网站的域名WordPress如何禁止游客访问
  • 搬家网站建设思路邯郸房产
  • 网站备案 换域名云南楚雄旅游必去的景点
  • 网站设计分析案例手机做ppt免费模板
  • 怎么用ps做静态网站网站建设增值服务
  • 做定制校服的网站绿色企业网站模板
  • 建设网站企业网上银行登录入口官方网络网站推广选择乐云seo
  • 福清市建设局网站多少海口网站建设呢
  • changer网站建设无锡做网站好
  • 门户网站怎么建设珠海通乘车码app更新版