? Redux 工具包注释?
Redux 是什么?
Redux 是 JS 应用程序的灵活状态容器,可以单独管理我们的应用程序状态。它在单个存储中管理应用程序状态,从而更轻松地处理整个应用程序中的复杂状态逻辑。
为什么要 Redux?
在正常流程中,我们需要进行道具钻探以在组件之间传递状态。有些级别不需要这里的状态,这是一种负担。此外,提升大型中型应用程序的状态并不是一个可扩展的解决方案,因为它需要进行结构性更改。这就是为什么我们需要 redux 来管理状态。这里的所有状态都保存在存储中,无论哪个组件需要,它们都可以订阅该存储。 Redux 通过强制执行单向数据流来确保可预测的状态管理、更轻松的调试并提高可扩展性。
Redux 核心组件:
操作: 描述发生的事情的对象。它通常包含一个类型和一个可选的有效负载。 (命令)
调度: 用于向存储发送操作以更新状态的函数。 (事件发生)
Reducer: 一个纯函数,它接受当前状态和一个操作,然后返回一个新状态。 (动作调度时触发的函数)
安装: npm i @reduxjs/toolkit react-redux
Redux 工作流程:
创建切片:
切片是单个功能的 Redux 减速器逻辑和操作的集合。准备回调允许我们在操作有效负载到达减速器之前对其进行自定义。
import { createSlice, nanoid } from "@reduxjs/toolkit"; const postSlice = createSlice({ name: "posts", initialState: [], reducers: { addPost: { reducer: (state, action) => { state.push(action.payload); }, prepare: (title, content) => ({ payload: { id: nanoid(), title, content }, }), }, deletePost: (state, action) => { return state.filter((post) => post.id != action.payload); }, }, }); export const { addPost, deletePost } = postSlice.actions; export default postSlice.reducer;
正在创建商店:
import { configureStore } from "@reduxjs/toolkit"; import postReducer from "../features/posts/postSlice"; export const store = configureStore({ reducer: { posts: postReducer }, });
与提供者一起包裹:
import { Provider } from "react-redux"; import { store } from "./app/store.jsx"; createRoot(document.getElementById("root")).render( <strictmode> <provider store="{store}"> <app></app> </provider> </strictmode> );
在组件中使用:
const PostList = ({ onEdit }) => { const posts = useSelector((state) => state.posts); const dispatch = useDispatch(); return ( <div classname="w-full grid grid-cols-1 gap-6 mt-12"> {posts.map((post) => ( <div key="{post.id}"></div> ))} </div> ); };
Redux 浏览器扩展: Redux DevTools
const store = configureStore({ reducer: rootReducer, devTools: process.env.NODE_ENV !== 'production', });
Redux 中的异步操作(Redux Thunk):
在 Redux 中,异步操作(如 API 调用)是使用中间件处理的,因为 Redux 默认情况下仅支持同步状态更新。用于处理异步操作的最常见中间件是 Redux Thunk、带有 createAsyncThunk 的 Redux Toolkit (RTK) 和 Redux Saga。
实施:
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; // Fetch all posts export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => { const response = await fetch('https://jsonplaceholder.typicode.com/posts'); return response.json(); }); // Initial State const initialState = { posts: [], post: null, loading: false, error: null, }; // Slice const postsSlice = createSlice({ name: 'posts', initialState, reducers: {}, extraReducers: (builder) => { builder // Fetch all posts .addCase(fetchPosts.pending, (state) => { state.loading = true; }) .addCase(fetchPosts.fulfilled, (state, action) => { state.loading = false; state.posts = action.payload; }) .addCase(fetchPosts.rejected, (state, action) => { state.loading = false; state.error = action.error.message; }) }, }); export default postsSlice.reducer;
用例:
import React, { useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { fetchPosts, createPost, updatePost, deletePost } from './postsSlice'; const Posts = () => { const dispatch = useDispatch(); const { posts, loading, error } = useSelector((state) =>state.posts); useEffect(() => { dispatch(fetchPosts()); }, [dispatch]); const handleCreate = () => { dispatch(createPost({ title: 'New Post', body: 'This is a new post' })); }; if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return ( <div> <h1 id="Posts">Posts</h1> <button onclick="{handleCreate}">Create Post</button> </div> ); }; export default Posts;
中间件
Redux 中的中间件拦截分派的操作,允许日志记录、崩溃报告或处理异步逻辑。中间件让我们可以自定义调度过程。
const blogPostMiddleware = (storeAPI) => (next) => (action) => { if (action.type === 'posts/publishPost') { const contentLength = action.payload.content.length; if (contentLength getDefaultMiddleware().concat(blogPostMiddleware), });
选择器
选择器有助于访问该州的特定部分。
export const selectCount = (state) =>状态.计数器.值;
错误处理
通过适当的状态管理有效地处理错误。
import { createSlice, nanoid } from "@reduxjs/toolkit"; const postSlice = createSlice({ name: "posts", initialState: [], reducers: { addPost: { reducer: (state, action) => { state.push(action.payload); }, prepare: (title, content) => ({ payload: { id: nanoid(), title, content }, }), }, deletePost: (state, action) => { return state.filter((post) => post.id != action.payload); }, }, }); export const { addPost, deletePost } = postSlice.actions; export default postSlice.reducer;
RTK 查询(简化数据获取)
RTK 查询简化了数据获取、缓存和同步。 RTK 查询自动缓存请求并避免不必要的重新获取,从而提高性能。
设置 RTK 查询
import { configureStore } from "@reduxjs/toolkit"; import postReducer from "../features/posts/postSlice"; export const store = configureStore({ reducer: { posts: postReducer }, });
组件中的使用
import { Provider } from "react-redux"; import { store } from "./app/store.jsx"; createRoot(document.getElementById("root")).render( <strictmode> <provider store="{store}"> <app></app> </provider> </strictmode> );
使用 Immer 进行不可变更新
Immer 允许我们编写直接“改变”状态的逻辑,同时保持更新在幕后不可变。
const PostList = ({ onEdit }) => { const posts = useSelector((state) => state.posts); const dispatch = useDispatch(); return ( <div classname="w-full grid grid-cols-1 gap-6 mt-12"> {posts.map((post) => ( <div key="{post.id}"></div> ))} </div> ); };
变异与不可变
Mutate:直接更改数据。例如,修改对象或数组。
不可变:我们不是直接修改数据,而是创建一个应用更改的新副本,保持原始数据不变。
Immer 的工作原理
Immer 帮助我们编写看起来像是在改变数据的代码(即直接更改数据),但它会自动使更改在幕后保持不变。这对于在处理 JavaScript 中的不可变数据结构时避免常见错误很有用。
示例:没有 Immer(突变):
const store = configureStore({ reducer: rootReducer, devTools: process.env.NODE_ENV !== 'production', });
使用 Immer(不变性):
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; // Fetch all posts export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => { const response = await fetch('https://jsonplaceholder.typicode.com/posts'); return response.json(); }); // Initial State const initialState = { posts: [], post: null, loading: false, error: null, }; // Slice const postsSlice = createSlice({ name: 'posts', initialState, reducers: {}, extraReducers: (builder) => { builder // Fetch all posts .addCase(fetchPosts.pending, (state) => { state.loading = true; }) .addCase(fetchPosts.fulfilled, (state, action) => { state.loading = false; state.posts = action.payload; }) .addCase(fetchPosts.rejected, (state, action) => { state.loading = false; state.error = action.error.message; }) }, }); export default postsSlice.reducer;
这使得使用 Redux(或任何状态管理)变得更容易,因为我们不必手动克隆和更新状态; Immer 自动为我们做这件事。
Redux 持久化:
为了在页面刷新时保持 Redux 状态,我们可以集成 Redux Persist。这会将您的 Redux 状态存储在本地存储或会话存储中,并在刷新应用程序时重新加载它。
安装:
npm install redux-persist
实施:
import React, { useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { fetchPosts, createPost, updatePost, deletePost } from './postsSlice'; const Posts = () => { const dispatch = useDispatch(); const { posts, loading, error } = useSelector((state) =>state.posts); useEffect(() => { dispatch(fetchPosts()); }, [dispatch]); const handleCreate = () => { dispatch(createPost({ title: 'New Post', body: 'This is a new post' })); }; if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return ( <div> <h1 id="Posts">Posts</h1> <button onclick="{handleCreate}">Create Post</button> </div> ); }; export default Posts;
用 Persisit Gate 包裹:
const blogPostMiddleware = (storeAPI) => (next) => (action) => { if (action.type === 'posts/publishPost') { const contentLength = action.payload.content.length; if (contentLength getDefaultMiddleware().concat(blogPostMiddleware), });
可选增强功能
使用 sessionStorage 而不是 localStorage:
将存储更改为基于会话(浏览器关闭时清除):
initialState: { items: [], status: 'idle', error: null, }, .addCase(fetchData.rejected, (state, action) => { state.status = 'failed'; state.error = action.error.message; });
选择性坚持:
只保留状态的特定部分:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; const api = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ baseUrl: 'https://jsonplaceholder.typicode.com' }), endpoints: (builder) => ({ getPosts: builder.query({ query: () => '/posts', }), getPostById: builder.query({ query: (id) => `/posts/${id}`, }), createPost: builder.mutation({ query: (newPost) => ({ url: '/posts', method: 'POST', body: newPost, }), }), updatePost: builder.mutation({ query: ({ id, ...updatedPost }) => ({ url: `/posts/${id}`, method: 'PUT', body: updatedPost, }), }), deletePost: builder.mutation({ query: (id) => ({ url: `/posts/${id}`, method: 'DELETE', }), }), }), }); export const { useGetPostsQuery, useGetPostByIdQuery, useCreatePostMutation, useUpdatePostMutation, useDeletePostMutation, } = api; export default api;
我创建了一个简单的博客项目,其中包含react、redux和具有CRUD功能的ant design。你可以去看看。
项目链接 - Redux 博客应用
?掌握 Redux Toolkit 并提升您的 React 应用!
以上是面向 React 开发人员的综合 Redux 工具包说明的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

本教程向您展示了如何将自定义的Google搜索API集成到您的博客或网站中,提供了比标准WordPress主题搜索功能更精致的搜索体验。 令人惊讶的是简单!您将能够将搜索限制为Y

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

本文系列在2017年中期进行了最新信息和新示例。 在此JSON示例中,我们将研究如何使用JSON格式将简单值存储在文件中。 使用键值对符号,我们可以存储任何类型的

利用轻松的网页布局:8个基本插件 jQuery大大简化了网页布局。 本文重点介绍了简化该过程的八个功能强大的JQuery插件,对于手动网站创建特别有用

核心要点 JavaScript 中的 this 通常指代“拥有”该方法的对象,但具体取决于函数的调用方式。 没有当前对象时,this 指代全局对象。在 Web 浏览器中,它由 window 表示。 调用函数时,this 保持全局对象;但调用对象构造函数或其任何方法时,this 指代对象的实例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。这些方法使用给定的 this 值和参数调用函数。 JavaScript 是一门优秀的编程语言。几年前,这句话可

jQuery是一个很棒的JavaScript框架。但是,与任何图书馆一样,有时有必要在引擎盖下发现发生了什么。也许是因为您正在追踪一个错误,或者只是对jQuery如何实现特定UI感到好奇

该帖子编写了有用的作弊表,参考指南,快速食谱以及用于Android,BlackBerry和iPhone应用程序开发的代码片段。 没有开发人员应该没有他们! 触摸手势参考指南(PDF) Desig的宝贵资源


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3汉化版
中文版,非常好用

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 Linux新版
SublimeText3 Linux最新版

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。