Redux Toolkit 用法、解决原生Redux 冗余问题

0 阅读3分钟

Redux Toolkit(RTK) 是 Redux Toolkit 官方推荐的 Redux 开发方式,用来解决原生 Redux 配置复杂、模板代码过多的问题。


一、原生 Redux 为什么“冗余”

传统 Redux 一个简单计数器,通常要写:

1. actionTypes

export const INCREMENT = 'INCREMENT'
export const DECREMENT = 'DECREMENT'

2. actions

export const increment = () => ({
  type: INCREMENT
})

export const decrement = () => ({
  type: DECREMENT
})

3. reducer

const initState = {
  count: 0
}

export default function reducer(state = initState, action) {
  switch(action.type) {
    case INCREMENT:
      return {
        ...state,
        count: state.count + 1
      }

    case DECREMENT:
      return {
        ...state,
        count: state.count - 1
      }

    default:
      return state
  }
}

4. store

import { createStore, combineReducers } from 'redux'

const store = createStore(rootReducer)

问题:

  • action type 重复
  • action creator 重复
  • switch-case 冗长
  • immutable 更新麻烦
  • store 配置复杂
  • thunk middleware 还得手动装

所以 Redux Toolkit 出来了。


二、Redux Toolkit 核心思想

RTK 帮你:

✅ 自动生成 action
✅ 自动处理 immutable
✅ 自动配置 thunk
✅ 简化 reducer
✅ 简化 store
✅ 规范化 Redux 写法


三、Redux Toolkit 核心 API

最常用:

API作用
configureStore创建 store
createSlice创建 reducer + action
createAsyncThunk处理异步
useSelector获取状态
useDispatch派发 action

四、Redux Toolkit 基础用法


1. 安装

npm install @reduxjs/toolkit react-redux

2. 创建 slice

counterSlice.js

import { createSlice } from '@reduxjs/toolkit'

const counterSlice = createSlice({
  name: 'counter',

  initialState: {
    count: 0
  },

  reducers: {
    increment(state) {
      state.count += 1
    },

    decrement(state) {
      state.count -= 1
    },

    add(state, action) {
      state.count += action.payload
    }
  }
})

export const {
  increment,
  decrement,
  add
} = counterSlice.actions

export default counterSlice.reducer

createSlice 做了什么

它自动帮你生成:

action

increment()

自动生成:

{
  type: 'counter/increment'
}

reducer

内部自动生成:

switch(action.type)

你不用写了。


五、configureStore

store.js

import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './counterSlice'

export const store = configureStore({
  reducer: {
    counter: counterReducer
  }
})

configureStore 优势

自动:

✅ combineReducers
✅ redux-thunk
✅ Redux DevTools
✅ 中间件配置

原生 Redux:

createStore(
  rootReducer,
  applyMiddleware(thunk)
)

RTK:

configureStore()

结束。


六、React 中使用


1. Provider 注入

main.jsx

import ReactDOM from 'react-dom/client'
import { Provider } from 'react-redux'
import { store } from './store'

root.render(
  <Provider store={store}>
    <App />
  </Provider>
)

2. 页面使用

Counter.jsx

import { useSelector, useDispatch } from 'react-redux'
import { increment, decrement, add } from './counterSlice'

function Counter() {
  const count = useSelector(state => state.counter.count)

  const dispatch = useDispatch()

  return (
    <div>
      <h1>{count}</h1>

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

      <button onClick={() => dispatch(decrement())}>
        -
      </button>

      <button onClick={() => dispatch(add(10))}>
        +10
      </button>
    </div>
  )
}

七、为什么 RTK 可以直接修改 state?

这里很多人误解。

你看到:

state.count += 1

实际上 Redux 仍然是不可变的。

RTK 内部用了:

Immer

Immer

它会:

state.count += 1

自动转换成:

return {
  ...state,
  count: state.count + 1
}

所以:

✅ 写法像“可变”
✅ 实际还是 immutable


八、异步请求 createAsyncThunk

这是 RTK 最大优势之一。


原生 Redux 异步

需要:

  • redux-thunk
  • loading
  • success
  • fail
  • actionTypes
  • actionCreators

非常繁琐。


RTK 写法

userSlice.js

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

export const fetchUser = createAsyncThunk(
  'user/fetchUser',

  async (id) => {
    const res = await fetch(
      `https://jsonplaceholder.typicode.com/users/${id}`
    )

    return await res.json()
  }
)

const userSlice = createSlice({
  name: 'user',

  initialState: {
    user: null,
    loading: false
  },

  reducers: {},

  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => {
        state.loading = true
      })

      .addCase(fetchUser.fulfilled, (state, action) => {
        state.loading = false
        state.user = action.payload
      })

      .addCase(fetchUser.rejected, (state) => {
        state.loading = false
      })
  }
})

export default userSlice.reducer

自动生成三种状态

RTK 自动帮你生成:

fetchUser.pending
fetchUser.fulfilled
fetchUser.rejected

不用手写。


九、RTK 项目推荐目录结构

src
 ├── store
 │    ├── index.js
 │    ├── userSlice.js
 │    └── counterSlice.js
 │
 ├── pages
 ├── components
 └── App.jsx

大型项目:

src
 ├── store
 │    ├── modules
 │    │     ├── user
 │    │     │    ├── index.js
 │    │     │    ├── actions.js
 │    │     │    └── selectors.js

十、RTK vs 原生 Redux

对比原生 ReduxRedux Toolkit
action types手写自动生成
reducerswitch-casecreateSlice
immutable手动展开Immer 自动
store配置复杂configureStore
thunk手动装默认内置
代码量很多很少
官方推荐

十一、现在企业基本怎么用?

现在 React 项目:

大部分:

React + Redux Toolkit + React-Redux

而不是:

React + Redux

RTK 已经是 Redux 官方标准。


十二、你现在最该掌握的

真正工作高频:

必会

  • createSlice
  • configureStore
  • useSelector
  • useDispatch
  • createAsyncThunk

进阶

  • RTK Query
  • middleware
  • redux-persist
  • selector优化
  • normalize 数据结构

十三、面试高频问题


1. Redux Toolkit 为什么解决 Redux 冗余?

核心:

  • 自动生成 action
  • 自动 immutable
  • 不用 switch-case
  • store 自动配置
  • thunk 默认集成

2. createSlice 做了什么?

同时生成:

  • reducer
  • actions
  • action types

3. RTK 为什么能直接修改 state?

因为内部使用了:

Immer


4. createAsyncThunk 有什么作用?

简化:

  • loading
  • success
  • fail

异步状态管理。


十四、推荐你现在这样学习

你有 React 基础的话,建议路线:

Redux 基础原理
    ↓
Redux Toolkit
    ↓
createAsyncThunk
    ↓
RTK Query
    ↓
项目实战

十五、一个最简 RTK 工作流

createSlice
    ↓
生成 reducer + actions
    ↓
configureStore 注册
    ↓
Provider 注入
    ↓
组件 useSelector/useDispatch