目录
介绍
安装依赖
初始化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
PayloadAction定义reducer payload的传参类型
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用于派发action,对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,做一些逻辑处理,return payload,
做过处理的action被reducer的action所接收。
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