是 Redux 官方强烈推荐,开箱即用的一个高效的 Redux 开发工具集。它旨在成为标准的 Redux 逻辑开发模式,我们强烈建议你使用它。
它包括几个实用程序功能,这些功能可以简化最常见场景下的 Redux 开发,包括配置 store、定义 reducer,不可变的更新逻辑、甚至可以立即创建整个状态的 “切片 slice”,而无需手动编写任何 action creator 或者 action type。它还自带了一些最常用的 Redux 插件,例如用于异步逻辑 Redux Thunk,用于编写选择器 selector 的函数 Reselect ,你都可以立刻使用。
-
本质:redex和redux-thunk进行封装
-
核心:
-
仓库,存放全局数据
-
reducer:定义修改该数据的行为(方法)的
-
actions:行为
# NPM npm install @reduxjs/toolkit # Yarn yarn add @reduxjs/toolkit
Redux Toolkit API文档:
-
configureStore:
-
作用:创建仓库,返回值就是一个仓库
-
语法:let store = configureStore({各自的reducer}) ; // 合并reducer
代码实现:在store文件夹创建一个index.js文件,在里面引入各自的reduce,集中关联 reducer
-
import {configureStore,createSlice} from '@reduxjs/toolkit' import meReducer from './modules/MeState' import cartReducer from './modules/CartState' import LimitReducer from './modules/LimitState' //configureStore =》语法 //返回值 =》就是仓库 //configureStore({各自的reducer}) =>合并reducer //创建仓库 const store = configureStore({ reducer: { //模块化对象 me:meReducer, cart:cartReducer, limit:LimitReducer } }) console.log(store); // export default store //创建仓库 =》让仓库和react 进行关联 react-redux export default store
-
createSlice:
-
作用:存放仓库中的数据,和定义仓库的行为(创建各自的reducer)
-
语法:let Mystate= createSlice({ }); // 创建reducer,存放数据initalState,定义行为reducers
-
import {createSlice} from '@reduxjs/toolkit' // 创建 reducer => 存放仓库数据,和定义仓库的行为 // 作用:createSlice => 创建 各自的reducer // 语法 // 返回值 = createSlice => 对象 // createSlice({实例属性}) let MeState=createSlice({ name:'me', // 作用域 唯一标识 => 我的模块存放的全局数据 initialState:{ name:'我是小明', age:20, num:100, }, // reducer =》 定义方法修改仓库中的数据 // 相对 vue muations => 定义修改 仓库中的数据 reducers:{ changeName(state,val){ // 第一个参数 就是这个仓库的存放(模板)的数据 第二个参数 就是 调用这个方法传递过来的数据 console.log(val); // 重新创建仓库数据吗?return {num:最新的数据} => state.name=val.payload; // 就是对数据进行更新 }, addAge(state){ state.age+=1; }, addNum(state,val){ state.num=state.num+val.payload; } } }) console.log(MeState); // 将行为暴露出去 export let {changeName,addAge,addNum}=MeState.actions // 本质就是将这个方法暴漏出去 export default MeState.reducer
核心:为我们react项目提供的一个组件,两个hooks
组件:Provider 1 作用:在父级组件中提供数据 ,其他的子集组件就可以获取到;
2 在父组件中提供了数据 store;
hooks:
useSelector: 1 作用:在组件中获取仓库中的数据,再通过useState修改数据方法,让数据更新
2 语法:useSelector(state => { return 返回值}) // 返回 在仓库中获取的数据
useDispatch 1 作用:可以获取到更新组件的dispatch,先触发reducer,
2 语法:let dispatch=useDispatch(); dispatch({type:'add'});
1. 安装react-redux
npm i react-redux
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import { Provider } from 'react-redux'; import store from './store'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <Provider store={store}> <App /> </Provider> );
import './App.css'; // (1)引入 react-redux 中提供的两个方法 import { useSelector,useDispatch } from 'react-redux'; // (2) 在页面(组件中获取数据) import {add,sub,addLIst,subList} from './store/modules/CartState' import { changeName,addNum} from './store/modules/MeState'; function App() { let dispatch=useDispatch(); // (3) 注意我们的行为 => 需要我们暴露处理 => 而这些行为就是reducers中定义的方法 let state =useSelector(store=>store); console.log(state) return ( <div className="App"> <h2> 获取到仓库中的数据{state.me.name}</h2> <h3>CartState {state.cart.num}</h3> <h3>MeState {state.me.num}</h3> {/* 修改仓库中数据 三点核心属性: reducer actions => dispatch(行为) store */} <button onClick={()=>{dispatch(changeName("我不是小明"))}}>修改MeName中的数据</button> <button onClick={()=>{dispatch(add(10))}}>修改CartState仓库中的数据num</button> <button onClick={()=>{dispatch(addNum(10))}}>修改MeState仓库中的数据num</button> </div> ); } export default App;
五、处理仓库中的复杂数据类型
处理方法:就是使用操作复杂数据类型的方法
import {configureStore,createSlice} from '@reduxjs/toolkit' //创建reducer =>createSlice let reducerNum = createSlice({ name:'nums',// 空间命名 initialState:{ num:2, list:[1,2,3,4,5] }, // 相对于vue mutations =》 定义方法修改 仓库中的数据 reducers:{ //在这里定义的方法 (1)第一个参数 当前reducer 的数据 (2) actions add(state,data){ console.log(state,data.payload); // 重新创建仓库数据吗? return {num:最新的数据} =》 state.num = state.num+data.payload // 就是对数据进行更新 }, reduce(state){ state.num = state.num -1 }, // 写的方法寓意化一下 addList(state,data){ state.list.push(data.payload) }, reduceList(state,data){ state.list.splice(data.payload,1) } } }) //注意 暴露actions export let {add,reduce,addList,reduceList} = reducerNum.actions // console.log( reducerNum); // 创建 store //configureStore => 创建仓库 // 语法: configureStore({ reducer:{}}) export default configureStore({ reducer:{ //写reducer reducerNum:reducerNum.reducer } })
import {add,reduce,addList,reduceList} from './store/index' function App() { let {num,list} = useSelector(store=>store.reducerNum) //{num,list} let dispatch = useDispatch() // console.log(store); return ( <div className="App"> <h2>toolkit</h2> <h2>{num}</h2> <button onClick={()=>dispatch(add(2))}>+</button> <button onClick={()=>dispatch(reduce())}>-</button> { list.map((item,index)=>{ return<div key={index} onClick={()=>dispatch(reduceList(index))}>{item}</div> }) } <button onClick={()=>dispatch(addList(1000))}>添加list</button> </div> ); }
六、处理异步问题
之前在redux中需要引入 第三方插件:react-thunk,而使用了redux Tookit是内置了react-thunk,
// 自己定义异步actions // 1 获取到异步的数据,再触发reducer => 修改仓库中的数据 // 2 定义 actions export function getRouterData(){ // 异步actions // 1 获取到异步的数据 function getData(){ // get需要传参,否则会报错 return axios.get('').then(res=>{ // 获取到的是异步的数据 let routerList=[1,2,3,4,5]; return routerList }) } // 2 再触发 reducer return async (dispatch)=>{ // 返回的处理方法的第一个参数就是 dispatch let data =await getData(); // 获取到异步的数据 dispatch(addRouter(data)) } }
2.需要在reducer 定义方法,然后在组件中操作这个方法
import {createSlice} from '@reduxjs/toolkit'; import axios from 'axios'; let LimitState=createSlice({ name:'limit', initialState:{ router:[] }, reducers:{ // 只能处理同步问题的问题 addRouter(state,data){ console.log('获取到异步的路由信息',data); // router 的数据是后端给的 payload state.router=data.payload } } }) // 注意 => 暴露两个 // 1 reducers 中的行为 => 那个组件使用直接引入 export let {addRouter}=LimitState.actions; export default LimitState.reducer;
3. 在组件中触发异步actions,
1. dispatch(异步actions方法的调用),调用的这个是异步actions的方法,然后再通过reduceer修改异步数据
import './App.css'; // (1)引入 react-redux 中提供的两个方法 import { useSelector,useDispatch } from 'react-redux'; // (2) 在页面(组件中获取数据) import { getRouterData } from './store/modules/LimitState'; function App() { let dispatch=useDispatch(); let state =useSelector(store=>store); console.log(state) return ( <div className="App"> <h2> 获取到仓库中的数据{state.limit.router}</h2> <button onClick={()=>dispatch(getRouterData())}>仓库中获取到异步的数据</button> </div> ); } export default App;