Title

Redux Toolkit 是什么?

Redux Toolkit 是 Redux 官方强烈推荐,开箱即用的一个高效的 Redux 开发工具集。它旨在成为标准的 Redux 逻辑开发模式,我们强烈建议你使用它。

它包括几个实用程序功能,这些功能可以简化最常见场景下的 Redux 开发,包括配置 store、定义 reducer,不可变的更新逻辑、甚至可以立即创建整个状态的 “切片 slice”,而无需手动编写任何 action creator 或者 action type。它还自带了一些最常用的 Redux 插件,例如用于异步逻辑 Redux Thunk,用于编写选择器 selector 的函数 Reselect ,你都可以立刻使用。

  1. 本质:redex和redux-thunk进行封装

  2. 核心:

  • 仓库,存放全局数据

  • reducer:定义修改该数据的行为(方法)的

  • actions:行为

一、安装

# NPM
npm install @reduxjs/toolkit

# Yarn
yarn add @reduxjs/toolkit

二、创建文件夹store/index:创建仓库

Redux Toolkit API文档:

  1. configureStore

    1. 作用:创建仓库,返回值就是一个仓库

    2. 语法: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
  1. createSlice

    1. 作用:存放仓库中的数据,和定义仓库的行为(创建各自的reducer)

    2. 语法:let Mystate= createSlice({ }); // 创建reducer,存放数据initalState,定义行为reducers

在store/modules中创建MeState,定义reducer

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-redux,让仓库数据与react产生关联

核心:为我们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

2. 在index.js中使用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;

 

五、处理仓库中的复杂数据类型

处理方法:就是使用操作复杂数据类型的方法

  1. 使用configureStore创建仓库,使用createSlice定义reducer

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
   }
})

在组件中使用仓库:使用userSelector引入仓库总的reducer和方法actions

  1. 语法:let {actions} = userSelector(store=> store.reducerNum)

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,

  1. 定义异步acitons

// 自己定义异步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;

 

posted on 2023-02-22 18:07  chccee  阅读(554)  评论(0编辑  收藏  举报