1. First give you a learning panorama
The evolution of Redux (very important)
Redux (Classic)
- createStore
- reducer / action
- middleware(thunk、logger)
React-Redux
<Provider />connect
Hooks Era
useSelectoruseDispatch
Redux Toolkit (RTK, official recommendation)
configureStorecreateSlicecreateAsyncThunk- Built-in immer + thunk
RTK Query (server status)
- Request / cache / deduplication / invalidation
👉 Now 90% of Redux projects = Redux Toolkit + Hooks
2. The “essential problem” solved by Redux
Redux = Predictable global state management + explicit state change trajectory
What does Redux solve?
- Share state across components/cross levels
- Status changes can be tracked (time travel, logs)
- Extract state change logic from components
What is Redux not suitable for?
- form local state
- UI temporary state (hover / open)
- High frequency transient state (mousemove)
3. The core idea of Redux (no need to write code first)
1️⃣ Single data source (Single Store)
txt
UI → dispatch(action) → reducer → new state → UI2️⃣ The status is read-only
- Cannot
store.state.xxx = 1 - Only available via
dispatch
3️⃣ Use pure functions to update status
js
(state, action) => newStateThese three articles = Redux’s “Constitution”
4. Modern Redux (RTK) minimal mental model
What has Redux Toolkit done for you?
- Automatically combine reducers
- Automatically connect to thunk
- Automatic access to immer (you can "write mutable code")
- Works with DevTools out of the box
There are only 4 things you really need to understand
txt
Store
Slice
Dispatch
Selector5. Minimal RTK example from 0 to 1 (essence)
1️⃣ Create slice (state + reducer + action)
js
import { createSlice } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment(state) {
state.value++
},
addBy(state, action) {
state.value += action.payload
}
}
})
export const { increment, addBy } = counterSlice.actions
export default counterSlice.reducer⚠️ You can "change the state directly" here because of immer
2️⃣ Create store
js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer
}
})3️⃣ Inject React
js
import { Provider } from 'react-redux'
import { store } from './store'
root.render(
<Provider store={store}>
<App />
</Provider>
)4️⃣ Use it in components
js
import { useSelector, useDispatch } from 'react-redux'
import { increment } from './counterSlice'
function Counter() {
const value = useSelector(state => state.counter.value)
const dispatch = useDispatch()
return (
<button onClick={() => dispatch(increment())}>
{value}
</button>
)
}6. Implementation principles behind Redux
1️⃣What is Store?
Essentially:
js
{
getState,
dispatch,
subscribe
}2️⃣What did dispatch do?
txt
dispatch(action)
↓
rootReducer(currentState, action)
↓
生成 newState
↓
通知所有 subscribers3️⃣ How is React-Redux “accurately updated”?
- Each
useSelectoris a subscriber - Use quote comparison/equalityFn
- Fiber render phase triggers updates (rather than Redux active render)
- 👉 Redux doesn’t care how React is updated
- 👉 React-Redux doesn’t care how reducer is calculated
7. Asynchronous: Why use thunk / createAsyncThunk
Redux itself only supports synchronization
txt
dispatch({ type: 'ADD' })thunk allows dispatch to support functions
js
dispatch((dispatch, getState) => {
setTimeout(() => {
dispatch(addBy(10))
}, 1000)
})RTK’s standard asynchronous scheme
js
export const fetchUser = createAsyncThunk(
'user/fetch',
async (id) => {
const res = await fetch(`/api/user/${id}`)
return res.json()
}
)Automatically generated:
- pending
- fulfilled
- rejected
8. When should you use Redux?
✅Suitable
- User information/permissions
- Global configuration
- Complex business state machine
- Multi-page sharing status
❌ Not suitable
- UI state (Modal/Tabs)
- form
- Simple father-son communication