Next.js ts redux/toolkit状态管理

news2024/10/6 23:24:24

目录

介绍

安装依赖

初始化store

1、在src下创建store文件夹,

2、创建最简单的slice切片

3、创建入口文件index.ts

4、创建hooks.ts

在_app.tsx中注入store

tsx中使用store

payload

createAsyncThunk

效果


介绍

@reduxjs/toolkit是Redux 官方提供的一个工具集,旨在简化和改善 Redux 应用的开发体验。它包含一些工具函数和约定,可以帮助你更快、更轻松地构建和维护 Redux 应用。

方法:

  • configureStore: 创建Redux store
  • createSlice :用于创建state和reducer
  • createAsyncThunk:用于处理异步操作,并自动创建了三个状态(pending、fulfilled、rejected)对应于异步操作的不同阶段。
  • ...

类型:

  • PayloadAction:用于定义往reducer传入action的类型

安装依赖

npm i @reduxjs/toolkit react-redux

yarn add @reduxjs/toolkit react-redux

初始化store

1、在src下创建store文件夹,

2、创建最简单的slice切片

import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';
import type { RootState } from '.';
interface CounterStateProps {  // state 类型
  value: number;
}
const initialState: CounterStateProps = {  // state数据初始化
  value: 0,
};
export const counterSlice = createSlice({
  name: 'counter',
  initialState,  // state
  reducers: {
    decrementOne: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action: PayloadAction<number>) => {
      state.value += action.payload;
    }
  }
})
export const { decrementOne, incrementByAmount } = counterSlice.actions;  // 导出action
export const selectCount = (state: RootState) => state.count.value;  // 导出state的值
export default counterSlice.reducer;  // 导出reducer

3、创建入口文件index.ts

import { configureStore } from '@reduxjs/toolkit'
import counterReducers from './counterSlice'
const store = configureStore({
  reducer: {
    count: counterReducers
  }
})
export type RootState = ReturnType<typeof store.getState>  // 导出类型被hook所使用
export type AppDispatch = typeof store.dispatch
export default store

4、创建hooks.ts

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './'

export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

至此store结构

在_app.tsx中注入store

import { AppProps } from 'next/app';
import { Provider } from 'react-redux';
import Header from '@/components/Header';
import store from '@/store'
export default function MyApp({ Component, pageProps } :AppProps) {
    return (
        <Provider store={store}>
            <Header/>
            <Component {...pageProps} />
        </Provider>
    )
}

tsx中使用store

import { useAppSelector, useAppDispatch } from '@/store/hooks'
import { selectCount, decrementOne ,incrementByAmount  } from '@/store/counterSlice'
export default function Redux() {
  const count = useAppSelector(selectCount)
  const dispatch = useAppDispatch()
  return (
    <>
      <div>value: {count}</div>
      <div>
        <button onClick={() => dispatch(decrementOne())}>increment</button>
        <button onClick={() => dispatch(incrementByAmount(1))}>incrementByAmount</button>
      </div>
    </>
  )
}

useAppSelector用于从store中取出数据

useAppDispatch用于派发reducer,对state进行操作,类似vuex里的mutation

payload

将传递给reducer的action做预处理

  reducers: {
    increment: {
      reducer(state, action: PayloadAction<{title: number; content: number; value:number}>) {
        state.value +=  action.payload.value
      },
      prepare(value: number) {
        return {
          payload: {
            title: 1,
            content: 2,
            value
          },
        };
      }
    },
 }
//tsx

<button onClick={() => dispatch(increment(1))}>increment</button>

dispatch(increment(1)) 后会先走prepare,传入参数value为1,做一些逻辑处理,返回payload,

处理的数据将被reducer的actionPayload所接收。

createAsyncThunk

createAsyncThunk是 Redux Toolkit 提供的一个用于创建处理异步操作的 thunk 函数的辅助函数

import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';
import type { RootState } from '.';

// 异步操作
export const fetchList = createAsyncThunk('counter/fetchList', async () => {
  const response = await fetch(`http://127.0.0.1:3000/api/v1/list`);
  return await response.json();
});

interface CounterStateProps {
  listLoading: boolean;
  listError: string;
  list: any[];
}

const initialState: CounterStateProps = {
  listLoading: false,
  listError: '',
  list: [],
};

const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    cleartListError: (state) => {
      state.listError = '';
    },
  },
  extraReducers(builder) {
    builder.addCase(fetchList.pending, (state) => {
      state.listLoading = true;
    })
    builder.addCase(fetchList.fulfilled, (state, action: PayloadAction<{data?: any, message?: string}>) => {
      const { data, message } = action.payload
      message ? state.listError = message : state.list = data.data;
      state.listLoading = false;
    })
    builder.addCase(fetchList.rejected, (state) => {
      state.listLoading = false;
    });
  },
})
export const { cleartListError } = counterSlice.actions;
export const selectList = (state: RootState) => state.counter.list;
export const selectListLoading = (state: RootState) => state.counter.listLoading;
export const selectListError = (state: RootState) => state.counter.listError;

export default counterSlice.reducer;

用createAsyncThunk创建异步操作,第一个参数是标识符,用于被Redux DevTools所记录

第二个异步回调的返回值传递给

用builder.addCase监听fetchList 异步操作,有三个状态pending、fulfilled、rejected,根据三种状态设置loading和error

在tsx中应用

import { useAppSelector, useAppDispatch } from '@/store/hooks'
import { selectListLoading, selectListError, selectList, fetchList, cleartListError  } from '@/store/counterSlice'
import { Skeleton, message } from 'antd'
import { useEffect } from 'react'
export default function Redux() {
  const [messageApi, contextHolder] = message.useMessage();
  const listLoading = useAppSelector(selectListLoading)
  const listError = useAppSelector(selectListError)
  const list = useAppSelector(selectList)
  const dispatch = useAppDispatch()
  const warning = (msg: string) => {
    messageApi.open({
      type: 'warning',
      content: msg,
    });
  };
  useEffect(() => {
    if(listError) {
      warning(listError)
      dispatch(cleartListError())
    }
  }, [listError])

  return (
    <>
      { contextHolder }
      <div>
        <button onClick={() => dispatch(fetchList())}>获取List</button>
      </div>
      <div>
        {
          listLoading ? 
          <Skeleton active /> :
          list.map((item, idx) => (
            <div key={idx}>{item.name}: {item.counter}</div>
          ))
        }
      </div>
    </>
  )
}

效果

success

error

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1307812.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C51--小车——L9110s电机驱动模块

电机模块开发&#xff1a; L9110s&#xff1a; 接通VCC&#xff0c;GND 模块电源指示灯亮。 IA1输入高电平&#xff0c;IA1输入低电平&#xff0c;【OA1 OB1】电机正转&#xff1b; IA1输入低电平&#xff0c;IA1输入高电平&#xff0c;【OA1 OB1】电机反转&#xff1b; IA2…

Java_Mybatis_动态SQL

一、动态SQL 1.概述 动态SQL&#xff1a; 是 MyBatis 的强大特性之一&#xff0c;解决拼接动态SQL时候的难题&#xff0c;提高开发效率分类 ifchoose(when,otherwise)trim(where,set)foreach 2.if 做 where 语句后面条件查询的,if 语句是可以拼接多条的 需求&#xff1a;根…

B站内容新爆点 | 高效引流、吸睛利器

11月29日&#xff0c;B站官方发布了2023年第三季度财报。财报显示&#xff0c;B站平台月均活跃用户数从第二季度3.24亿增长至3.41亿&#xff0c;再创新高&#xff0c;日均活跃用户数则突破一亿里程碑&#xff0c;达1.03亿&#xff0c;同比增长14%。用户日均使用时长首次超过100…

Java - Collectors.toMap() 使用

List 转 Map 一、Collectors.toMap() 函数源码定义&#xff1a; // 两个参数public static <T, K, U>Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper) {retu…

【数据结构】贪心算法

一.贪心算法的定义 贪心算法是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;只做出在某种意义上的局部最优解。 贪心算法的结果是最优解的最好近似。 优点&#xff1a;简单&#xff0c;高效。 缺点&…

慎用,Mybatis-Plus这个方法可能导致死锁

1 场景还原 1.1 版本信息 MySQL版本&#xff1a;5.6.36-82.1-log Mybatis-Plus的starter版本&#xff1a;3.3.2 存储引擎&#xff1a;InnoDB1.2 死锁现象 A同学在生产环境使用了Mybatis-Plus提供的 com.baomidou.mybatisplus.extension.service.IService#saveOrUpdate(T, co…

【MySQL】:表的约束(上)

表的约束 一.非空约束二.default约束三.列描述四.zerofill五.主键1.单个主键2.复合主键 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据的正确性。比如有…

孩子还是有一颗网安梦——Bandit通关教程:Level 11 → Level 12

&#x1f575;️‍♂️ 专栏《解密游戏-Bandit》 &#x1f310; 游戏官网&#xff1a; Bandit游戏 &#x1f3ae; 游戏简介&#xff1a; Bandit游戏专为网络安全初学者设计&#xff0c;通过一系列级别挑战玩家&#xff0c;从Level0开始&#xff0c;逐步学习基础命令行和安全概念…

随机变量的定义

试验E的样本空间为S&#xff0c;样本空间S中的元素记为e&#xff0c;即样本点是e&#xff0c;样本空间记成&#xff0c;表示元素组成的集合。 随机变量的定义&#xff1a;设随机变量的样本空间为&#xff0c;是定义在样本空间S上的实值单值函数&#xff0c;称为随机变量。 随机…

螺旋矩阵算法(leetcode第54题)

题目描述&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。示例 1&#xff1a;输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a;输入&#xff…

《深入理解 Android ART 虚拟机》笔记

Dex文件格式、指令码 一个Class文件对应一个Java源码文件&#xff0c;而一个Dex文件可对应多个Java源码文件。开发者开发一个Java模块&#xff08;不管是Jar包还是Apk&#xff09;时&#xff1a; 在PC平台上&#xff0c;该模块包含的每一个Java源码文件都会对应生成一个同文件…

蝴蝶Butterfly 数据集VOC+yolo-2000张(labelImg标注)

蝴蝶被誉为“会飞的花朵”&#xff0c;是一类非常美丽的昆虫。蝴蝶大多数体型属于中型至大型&#xff0c;翅展在15~260毫米之间&#xff0c;有2对膜质的翅。体躯长圆柱形&#xff0c;分为头、胸、腹三部分。体及翅膜上覆有鳞片及毛&#xff0c;形成各种色彩斑纹。今天要介绍的是…

Mistral AI 推出高质量的稀疏专家混合AI人工智能模型——SMoE,有望超越ChatGPT3.5

Mistral AI&#xff08;“Mistral AI”是一家由前DeepMind和Meta Platforms&#xff08;META.US&#xff09;的研究人员组建的新公司。&#xff09;继续履行为开发者社区提供最佳开放模型的使命。他们发布了 Mixtral 8x7B&#xff0c;这是一个高质量的稀疏专家混合模型&#xf…

YOLOv8改进 | 2023主干篇 | 替换LSKNet遥感目标检测主干 (附代码+修改教程+结构讲解)

一、本文介绍 本文给大家带来的改进内容是LSKNet&#xff08;Large Kernel Selection, LK Selection&#xff09;&#xff0c;其是一种专为遥感目标检测设计的网络架构&#xff0c;其核心思想是动态调整其大的空间感受野&#xff0c;以更好地捕捉遥感场景中不同对象的范围上下…

【精选】SpringMVC简介及其执行流程,参数获取方式

SpringMVC简介 MVC模型 MVC全称Model View Controller&#xff0c;是一种设计创建Web应用程序的模式。这三个单词分别代表Web应用程序的三个部分&#xff1a; Model&#xff08;模型&#xff09;&#xff1a;指数据模型。用于存储数据以及处理用户请求的业务逻辑。在Web应用中&…

37.分支结构嵌套

目录 一.什么是分支结构嵌套 二.什么情况下会用分支结构嵌套 三.举例 四.注意事项 五.视频教程 一.什么是分支结构嵌套 在一个if语句中又包含了另外一个if语句&#xff0c;这种情况称之为if语句的嵌套&#xff0c;也叫做分支结构嵌套。 二.什么情况下会用分支结构嵌套 如…

dToF直方图之美_激光雷达多目标检测

直方图提供了一种简单有效的方法来分析信号分布并识别与目标存在相对应的峰值,并且能够可视化大量数据,让测距数形结合。在车载激光雷达中,对于多目标检测,多峰算法统计等,有着区别于摄像头以及其他雷达方案的天然优势。 如下图,当中有着清晰可见的三个峰值,我们可以非…

炸弹人游戏

代码实现 广度优先搜素 深度优先搜索

巧用RTL原语实现MUX门级映射

对于前端设计人员&#xff0c;经常会需要一个MUX来对工作模式&#xff0c;数据路径进行明确&#xff08;explicit&#xff09;的声明&#xff0c;这个对于中后端工程师下约束也很重要。这里介绍一种巧用的RTL原语&#xff0c;实现MUX的方法。闲言少叙&#xff0c;ICerGo&#x…

2023自动化测试框架大对比:哪个更胜一筹?

所谓工欲善其事&#xff0c;必先利其器&#xff0c;在进行自动化测试时&#xff0c;选择一个合适的框架是至关重要的。因为一个好的测试框架可以大大提高测试效率&#xff0c;减少我们很多工作量。在选择框架之前&#xff0c;我们通常需要对不同的框架进行对比&#xff0c;以便…