• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

React-redux ReduxToolkit 的使用和封装 同步和异步修改initialState内的数据 详细说明

武飞扬头像
桥志三
帮助1

目录

认识Redux Toolkit

安装Redux Toolkit:

 Redux Toolkit的核心API主要是如下几个:

configureStore:

createSlice:

createAsyncThunk:

store的创建

 将 store 内的数据 在app组件内共享

重构代码 – 创建counter的reducer

reducers 官方推荐同步修改 initialState 方法

使用 connect 函数将 store 内的数据映射到组件 props内

Redux Toolkit的异步操作

 extraReducer的另外一种写法

使用 hooks 操作redux-toolkit 


认识Redux Toolkit

        Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法。

        redux的编写逻辑过于的繁琐和麻烦。

        并且代码通常分拆在多个文件中(虽然也可以放到一个文件管理,但是代码量过多,不利于管理);

        Redux Toolkit包旨在成为编写Redux逻辑的标准方式,从而解决上面提到的问题;

        在很多地方为了称呼方便,也将之称为“RTK”;

安装Redux Toolkit:

npm install @reduxjs/toolkit react-redux

yarn add  @reduxjs/toolkit react-redux

pnpm install @reduxjs/toolkit react-redux

 Redux Toolkit的核心API主要是如下几个:

configureStore:

        包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension。

createSlice:

        接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的actions。

createAsyncThunk:

        接受一个动作类型字符串和一个返回承诺的函数,并生成一个pending/fulfilled/rejected基于该承诺分派动作类型的 thunk。

store的创建

        configureStore用于创建store对象,常见参数如下:

        reducer,将slice中的reducer可以组成一个对象传入此处;

        middleware:可以使用参数,传入其他的中间件;

        devTools:是否配置devTools工具,默认为true;

        在 src 目录下创建一个store 文件夹 文件夹内创建 index.js 文件

学新通

  1.  
    // npm install @reduxjs/toolkit react-redux -S
  2.  
    import { configureStore } from '@reduxjs/toolkit'
  3.  
    // 导入 namesReducer 进行使用
  4.  
    import namesReducer from './features/names'
  5.  
    import asyncListReducer from './features/asyncList'
  6.  
     
  7.  
    const store = configureStore({
  8.  
    reducer: {
  9.  
    names: namesReducer,
  10.  
    asyncList: asyncListReducer
  11.  
    },
  12.  
    // reduxjs/toolkit 默认是已经集成了 redux-thunk 和 redux-devtool 如果需要添加其他中间件可以使用middleware参数,传入其他的中间件
  13.  
    // middleware: [thunk, logger],
  14.  
     
  15.  
    // 是否配置 devTool 工具,默认为 true 开发环境建议 true 生产环境建议 false
  16.  
    devTools: true
  17.  
    })
  18.  
     
  19.  
    export default store
学新通

 将 store 内的数据 在app组件内共享

使用 react-redux 给我们提供的 Provider 包裹 App 组件 传入store 进行数据共享

  1.  
    import { Provider } from 'react-redux'
  2.  
    import store from './Redux-Toolkit的使用/store'
  3.  
    import App from './Redux-Toolkit的使用/App'
  4.  
     
  5.  
    // 编写 react 代码,并且通过 React 渲染出来对应的内容
  6.  
    const root = ReactDOM.createRoot(document.querySelector('#root'))
  7.  
    root.render(
  8.  
    <Provider store={store}>
  9.  
    <App name={'HachimanC'} />
  10.  
    </Provider>
  11.  
    )

重构代码 – 创建counter的reducer

创建 name.js 文件

 学新通

        我们先对names的reducer进行重构: 通过createSlice创建一个slice。

        createSlice主要包含如下几个参数:

        name:用户标记slice的名词

        在之后的redux-devtool中会显示对应的名词;

        initialState:初始化值

        第一次初始化时的值;

        reducers:相当于之前的reducer函数

        对象类型,并且可以添加很多的函数;

        函数类似于redux原来reducer中的一个case语句;

        函数的参数:

        ✓ 参数一:state

        ✓ 参数二:调用这个action时,传递的action参数;

        createSlice返回值是一个对象,包含所有的actions;

reducers 官方推荐同步修改 initialState 方法

      这里的 reducers 是react官方推荐的同步修改的方法

  1.  
    import { createSlice } from '@reduxjs/toolkit'
  2.  
    const nameSlice = createSlice({
  3.  
    // 当前store的唯一id
  4.  
    name: 'names',
  5.  
    // 默认值
  6.  
    initialState: {
  7.  
    names: 'HachimanC'
  8.  
    },
  9.  
    /*
  10.  
    reducer(state = initState, action){
  11.  
    case 语句1:
  12.  
    获取 action 根据 action 修改 state
  13.  
    case 语句2:
  14.  
    获取 action 根据 action 修改 state
  15.  
    }
  16.  
    */
  17.  
    // 这里的 reducers 是react官方推荐的同步修改的方法
  18.  
    reducers: {
  19.  
    addNamesAction(state, action) {
  20.  
    // action.payload 是传来的参数
  21.  
    console.log('addNamesAction', action)
  22.  
    state.names = state.names action.payload
  23.  
    },
  24.  
    subNamesAction(state, action) {}
  25.  
    }
  26.  
    })
  27.  
    export const { addNamesAction, subNamesAction } = nameSlice.actions
  28.  
    // 导出 nameSlice 内的 reducers
  29.  
    export default nameSlice.reducer
学新通

使用 connect 函数将 store 内的数据映射到组件 props内

学新通

  1.  
    import React, { PureComponent } from 'react'
  2.  
    import { connect } from 'react-redux'
  3.  
    import { addNamesAction } from './store/features/names'
  4.  
    export class Profile extends PureComponent {
  5.  
    addNames(nameValue) {
  6.  
    // console.log(nameValue)
  7.  
    this.props.addNamesHandler(nameValue)
  8.  
    }
  9.  
    render() {
  10.  
    const { names } = this.props
  11.  
    return (
  12.  
    <div>
  13.  
    <h2>Profile names: {names}</h2>
  14.  
    <button onClick={e => this.addNames(', lzumiShinichi')}>addNames</button>
  15.  
    <button onClick={e => this.addNames(', 大吉')}>addNames</button>
  16.  
    <button onClick={e => this.addNames(', OkabeRintaro')}>addNames</button>
  17.  
    </div>
  18.  
    )
  19.  
    }
  20.  
    }
  21.  
    const mapStateToProps = state => {
  22.  
    return {
  23.  
    names: state.names.names
  24.  
    }
  25.  
    }
  26.  
    const mapDispatchToProps = dispatch => ({
  27.  
    addNamesHandler(namesValue) {
  28.  
    dispatch(addNamesAction(namesValue))
  29.  
    }
  30.  
    })
  31.  
    export default connect(mapStateToProps, mapDispatchToProps)(Profile)
学新通

Redux Toolkit的异步操作

在之前的开发中,通过redux-thunk中间件让dispatch中可以进行异步操作。

Redux Toolkit默认已经给我们继承了Thunk相关的功能:createAsyncThunk

学新通

◼ 当createAsyncThunk创建出来的actiondispatch时,会存在三种状态:

pending:action被发出,但是还没有最终的结果;

fulfilled:获取到最终的结果(有返回值的结果);

rejected:执行过程中有错误或者抛出了异常;

◼ 我们可以在createSliceentraReducer中监听这些结果:

见下图

学新通

 学新通

 最后附上异步请求全部操作代码

学新通学新通

  1.  
    import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
  2.  
    import axios from 'axios'
  3.  
     
  4.  
    // 导出
  5.  
    export const fetchAsyceList = createAsyncThunk('fetch/async', async () => {
  6.  
    const { data } = await axios.get('http://123.207.32.32:8000/home/multidata')
  7.  
    // const banners = data.data.banner.list
  8.  
    // const recommend = data.data.recommend.list
  9.  
    return data.data
  10.  
    })
  11.  
     
  12.  
    const asyncListSlice = createSlice({
  13.  
    name: 'asyncListSlice',
  14.  
    initialState: {
  15.  
    banners: [],
  16.  
    recommend: []
  17.  
    },
  18.  
    reducers: {
  19.  
    changeBannerAction(state, { payload }) {},
  20.  
    changeRecommendAction(state, { payload }) {}
  21.  
    },
  22.  
    // 额外的 reducer 执行异步操作
  23.  
    extraReducers: {
  24.  
    // 计算属性名 [computedNames]
  25.  
    [fetchAsyceList.pending](state, action) {
  26.  
    console.log('fetchAsyncList 执行中还未有结果')
  27.  
    },
  28.  
    [fetchAsyceList.fulfilled](state, { payload }) {
  29.  
    console.log('fetchAsyncList 拿到结果了', payload)
  30.  
    state.banners = payload.banner.list
  31.  
    state.recommend = payload.recommend.list
  32.  
    },
  33.  
    [fetchAsyceList.rejected](state, action) {
  34.  
    console.log('fetchAsyncList 错误了')
  35.  
    }
  36.  
    }
  37.  
    })
  38.  
     
  39.  
    export const { changeBannerAction, changeRecommendAction } = asyncListSlice.actions
  40.  
     
  41.  
    export default asyncListSlice.reducer
学新通
  1.  
    import React, { PureComponent } from 'react'
  2.  
    import { connect } from 'react-redux'
  3.  
    import { fetchAsyceList } from './store/features/asyncList'
  4.  
    import { addNamesAction } from './store/features/names'
  5.  
     
  6.  
    export class Home extends PureComponent {
  7.  
    componentDidMount() {
  8.  
    this.props.fetchAsyncList()
  9.  
    }
  10.  
    addNames(nameValue) {
  11.  
    // console.log(nameValue)
  12.  
    this.props.addNamesHandler(nameValue)
  13.  
    }
  14.  
    render() {
  15.  
    const { names, banners, recommend } = this.props
  16.  
    return (
  17.  
    <div>
  18.  
    <h2>Home names: {names}</h2>
  19.  
    <button onClick={e => this.addNames(', ErenYeager')}>addNames</button>
  20.  
    <button onClick={e => this.addNames(', Ayanokoji')}>addNames</button>
  21.  
     
  22.  
    <div className="banners">
  23.  
    <h2>异步请求轮播图数据:</h2>
  24.  
    <ul>
  25.  
    {banners.map((item, index) => (
  26.  
    <li key={index}>{item.title}</li>
  27.  
    ))}
  28.  
    </ul>
  29.  
    </div>
  30.  
     
  31.  
    <div className="recommend">
  32.  
    <h2>异步请求推荐列表数据:</h2>
  33.  
    <ul>
  34.  
    {recommend.map((item, index) => (
  35.  
    <li key={index}>{item.title}</li>
  36.  
    ))}
  37.  
    </ul>
  38.  
    </div>
  39.  
    </div>
  40.  
    )
  41.  
    }
  42.  
    }
  43.  
     
  44.  
    const mapStateToProps = state => ({
  45.  
    names: state.names.names,
  46.  
    banners: state.asyncList.banners,
  47.  
    recommend: state.asyncList.recommend
  48.  
    })
  49.  
     
  50.  
    const mapDispatchToProps = dispatch => ({
  51.  
    addNamesHandler(nameValue) {
  52.  
    dispatch(addNamesAction(nameValue))
  53.  
    },
  54.  
    subNames() {},
  55.  
    fetchAsyncList() {
  56.  
    dispatch(fetchAsyceList())
  57.  
    }
  58.  
    })
  59.  
     
  60.  
    export default connect(mapStateToProps, mapDispatchToProps)(Home)
学新通

 extraReducer的另外一种写法

        extraReducer还可以传入一个函数,函数接受一个builder参数。

        我们可以向builder中添加case来监听异步操作的结果:

学新通

学新通

使用 hooks 操作redux-toolkit 

  1.  
    import React, { memo } from 'react'
  2.  
    import { shallowEqual, useDispatch, useSelector } from 'react-redux'
  3.  
    // import { connect } from 'react-redux'
  4.  
    import { addNumberAction, subNumberAction } from './store/modules/counter'
  5.  
     
  6.  
    const NamesCom = memo(() => {
  7.  
    console.log('names组件执行了一遍')
  8.  
    const { names } = useSelector(
  9.  
    state => ({
  10.  
    names: state.counter.names
  11.  
    }),
  12.  
    shallowEqual
  13.  
    )
  14.  
    return <h2>{names}</h2>
  15.  
    })
  16.  
     
  17.  
    const ReduxHooks = memo(props => {
  18.  
    // const { count, addNumberHandler, subNumberHandler } = props
  19.  
     
  20.  
    // 使用 useSelector 将 redux 中 store 的数据映射到组件内
  21.  
    const { count } = useSelector(
  22.  
    state => ({
  23.  
    count: state.counter.count
  24.  
    }),
  25.  
    // shallowEqual 可以对state.counter 内的 变量进行浅层比较 组件更新数据不会影响其他组件的渲染(性能优化)
  26.  
    shallowEqual
  27.  
    )
  28.  
    // 使用 useDispatch 派发 action 到 reducers 内
  29.  
    const dispatch = useDispatch()
  30.  
    const addNumberHandler = (num, isAdd) => {
  31.  
    if (isAdd) {
  32.  
    dispatch(addNumberAction(num))
  33.  
    return
  34.  
    }
  35.  
    dispatch(subNumberAction(num))
  36.  
    }
  37.  
    return (
  38.  
    <div>
  39.  
    <h2>ReduxHooks 使用</h2>
  40.  
    <h3>redux 里的count:{count}</h3>
  41.  
    <button onClick={e => addNumberHandler(5, true)}> 5</button>
  42.  
    <button onClick={e => addNumberHandler(5, false)}>-5</button>
  43.  
    <NamesCom />
  44.  
    <hr />
  45.  
    </div>
  46.  
    )
  47.  
    })
  48.  
     
  49.  
    // 不使用 hooks
  50.  
    // const mapStateToProps = state => ({
  51.  
    // count: state.counter.count
  52.  
    // })
  53.  
    // const mapDispatchToProps = dispatch => ({
  54.  
    // addNumberHandler(num) {
  55.  
    // dispatch(addNumber(num))
  56.  
    // },
  57.  
    // subNumberHandler(num) {
  58.  
    // dispatch(subNumber(num))
  59.  
    // }
  60.  
    // })
  61.  
    // export default connect(mapStateToProps, mapDispatchToProps)(ReduxHooks)
  62.  
     
  63.  
    export default ReduxHooks
学新通

Redux官方图 

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgagjhc
系列文章
更多 icon
同类精品
更多 icon
继续加载