Redux Toolkit 使用总结

简介

使用Redux ToolKit简化了传统redux创建的流程及代码量;借助createReducer和createSlice这两个钩子函数让我们更轻易的CRDU全局状态,同时在中间件中默认配置了thunk。

安装

yarn add @reduxjs/toolkit react-redux redux-logger

创建一个slice

import {createSlice, Draft} from '@reduxjs/toolkit'

//store的类型
export type UserStore={
  user: string
  isLogin: boolean
  text: string
}

//创建一个createSlice
const userStore = createSlice({
  name: 'user',
  initialState(){
    return {
      user: 'admin',
      isLogin: false,
      text: '未登录'
    } as UserStore
  },
  reducers: {
    login(state:Draft<UserStore>)  {
      state.isLogin=true
      state.text='已登录'
    },
    logout (state:Draft<UserStore>) {
      state.isLogin=false
      state.text='未登录'
    },
  }
})

//返回actions和reducer
export const { login, logout } = userStore.actions
export default userStore.reducer


定义store

import {configureStore} from '@reduxjs/toolkit'
import logger from 'redux-logger';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import countReducer from "./count";
import userReducer from './user'


export const store=configureStore({
  reducer: {
    count:countReducer,
    user:userReducer
  },
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})

export type RootState  = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export const useAppDispatch = () => useDispatch<AppDispatch>()


通过上下文传递store

import React from 'react';
import ReactDOM from 'react-dom/client';
import 'nprogress/nprogress.css';
import './style/index.css';
import {
  BrowserRouter as Router,
} from 'react-router-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { store } from './store';
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement,
);
root.render(
  <Router>
    <Provider store={store}>
      <App/>
    </Provider>
  </Router>
);

reportWebVitals();

组件内使用

import React from 'react';
import { asyncIncrement, decremented, incremented, } from '../store/count';
import { login, logout } from '../store/user';
import { RootState, useAppDispatch, useAppSelector } from '../store';

type Props = {}

const Test: React.FC<Props> = (props) => {
  const count = useAppSelector((state: RootState) => state.count.num);
  const user = useAppSelector((state: RootState) => state.user);
  const dispatch = useAppDispatch();
  return (
    <>
      <div>test</div>
      <div>{count}</div>
      <div>{JSON.stringify(user)}</div>
      <button onClick={() => dispatch(incremented(50))}>+50</button>
      <button onClick={() => dispatch(decremented(100))}>-100</button>
      <button onClick={() => {
        dispatch(asyncIncrement("/test"));
      }}>重置
      </button>
      <button onClick={() => dispatch(login())}>login</button>
      <button onClick={() => dispatch(logout())}>logout</button>
    </>
  );
};

export default Test;

关于异步

Redux ToolKit支持异步操作

import {
    createAsyncThunk,
    createSlice,
    Draft,
    PayloadAction
} from '@reduxjs/toolkit';

//mock一个请求
const ajax=(url:string)=>{
    return new Promise((resolve,reject)=>{
        if(url==='/test'){
            setTimeout(()=>{
                resolve({data:20})
            },2000)
        }
    })
}

//定义异步任务
export const asyncIncrement = createAsyncThunk('counter', async (url:string) => {
    return await ajax(url) as {data:number};
});

//store的类型
export type CountStore = {
    num: number
}


//创建一个store切片
const countStore = createSlice({
    name: 'counter',
    initialState() {
        return {
            num: 0
        } as CountStore
    },
    reducers: {
        incremented(state: Draft<CountStore>, action: PayloadAction<number>){
            state.num += action.payload
        },
        decremented(state: Draft<CountStore>, action: PayloadAction<number>) {
            state.num -= action.payload
        }
    },
    extraReducers: (builder) => {          //异步任务
        builder.addCase(asyncIncrement.fulfilled, (state, action) => {
            state.num=action.payload.data
        })
    },
})

//actions
export const {incremented, decremented} = countStore.actions
export default countStore.reducer




你可能感兴趣的:(react.js,javascript,前端)