创建React Store
创建名为 src/app/store.js的文件,并从Redux工具库中引入configureStore API。如此可创建一个空的Redux store并导出,如下:
app/store.js
import { configureStore } from '@reduxjs/toolkit'
export default configureStore({
reducer: {},
})
React使用Redux Store
React组件通过React Redux的Provider组件使用store,store作为Provider的props传递(其中store是用户创建的??)。代码示例:
app/store.js
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import store from './app/store'
import { Provider } from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
Redux State Slice
通过Redux Toolkit中的createSlice API创建一个state slice,其中需要三个核心要素:标识slice唯一性的string name、初始化的state、更新state的reducer方法。slice的创建采用immer语法。创建后,即可export actions和reducer方法。
slice是不可变的语法/模板,但Redux Toolkit的createSlice和createReducer APIs 使用Immer可以更新
features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
},
},
})
// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
Slice Reducers应用到Store
下一步将slice中的reducer方法应用到store。不同于第一步的创建空store,借助slice reducer可定义一个key为reducers的对象,store通过reducer方法更新slice中的state
app/store.js
import counterReducer from '../features/counter/counterSlice'
export default configureStore({
reducer: {
counter: counterReducer,
},
})
React组件中使用State和Actions
这里React Redux的hook API发挥作用,使用useSelector从store取数据,使用useDispatch 分发actions
features/counter/Counter.js
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'
import styles from './Counter.module.css'
export function Counter() {
const count = useSelector((state) => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
Increment
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
Decrement
</button>
</div>
</div>
)
}
总结&补充
slice: 定义state/数据集、action/更新state的方法、reducer方法 store: 隔离slice和组件, 其他组件派发/dispatch行为/actions给store,通过store更新state;其他组件订阅store中的状态state更新视图 react-redux: