为什么要使用 React-Redux 绑定库?
React 和 Redux 是两个独立的库,两者之间职责独立。因此,为了实现在 React 中使用 Redux 进行状态管理 ,就需要一种机制,将这两个独立的库关联在一起。这时候就用到 React-Redux 这个绑定库了。
react-redux 的使用分为两大步:1 全局配置(只需要配置一次) 2 组件接入(获取状态或修改状态)
先看全局配置:
步骤:
yarn add react-redux
核心代码:
src/index.js 中:
// 导入 Provider 组件
import { Provider } from 'react-redux'
// 导入创建好的 store
import store from './store'
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(
<Provider store={store}>
<App />
</Provider>
)
useSelector
:获取 Redux 提供的状态数据import { useSelector } from 'react-redux'
// Redux 中的状态是数值,所以,可以直接返回 state 本身
const count = useSelector(state => state)
// 比如,Redux 中的状态是个对象,就可以:
const list = useSelector(state => state.list)
例:
import { useSelector } from 'react-redux'
const App = () => {
const count = useSelector(state => state)
return (
<div>
<h1>计数器:{count}</h1>
<button>数值增加</button>
<button>数值减少</button>
</div>
)
}
useDispatch
:拿到 dispatch 函数,分发 action,修改 redux 中的状态数据
语法:
import { useDispatch } from 'react-redux'
// 调用 useDispatch hook,拿到 dispatch 函数
const dispatch = useDispatch()
// 调用 dispatch 传入 action,来分发动作
dispatch( action )
例:
import { useDispatch } from 'react-redux'
const App = () => {
const dispatch = useDispatch()
return (
<div>
<h1>计数器:{count}</h1>
{/* 调用 dispatch 分发 action */}
<button onClick={() => dispatch(increment(2))}>数值增加</button>
<button onClick={() => dispatch(decrement(5))}>数值减少</button>
</div>
)
}
在使用 Redux 进行项目开发时,不会将 action/reducer/store 都放在同一个文件中,而是会进行拆分
可以按照以下结构,来组织 Redux 的代码:
/store --- 在 src 目录中创建,用于存放 Redux 相关的代码
/actions --- 存放所有的 action
/reducers --- 存放所有的 reducer
index.js --- redux 的入口文件,用来创建 store
Action Type 指的是:action 对象中 type 属性的值
Redux 项目中会多次使用 action type,比如,action 对象、reducer 函数、dispatch(action) 等
目标:集中处理 action type,保持项目中 action type 的一致性
action type 的值采用:'domain/action'(功能/动作)形式
,进行分类处理,比如,
'counter/increment'
表示 Counter 功能中的 increment 动作'login/getCode'
表示登录获取验证码的动作'profile/get'
表示获取个人资料步骤:
actionTypes
目录或者 constants
目录,集中处理// actionTypes 或 constants 目录:
const increment = 'counter/increment'
const decrement = 'counter/decrement'
export { increment, decrement }
// --
// 使用:
// actions/index.js
import * as types from '../acitonTypes'
const increment = payload => ({ type: types.increment, payload })
const decrement = payload => ({ type: types.decrement, payload })
// reducers/index.js
import * as types from '../acitonTypes'
const reducer = (state, action) => {
switch (action.type) {
case types.increment:
return state + 1
case types.decrement:
return state - action.payload
default:
return state
}
}
注:额外添加 Action Type 会让项目结构变复杂,此操作可省略。但,domain/action
命名方式强烈推荐!
随着项目功能变得越来越复杂,需要 Redux 管理的状态也会越来越多
此时,有两种方式来处理状态的更新:
推荐:使用多个 reducer(第二种方案),每个 reducer 处理的状态更单一,职责更明确
此时,项目中会有多个 reducer,但是 store 只能接收一个 reducer,因此,需要将多个 reducer 合并为一根 reducer,才能传递给 store
合并方式:使用 Redux 中的 combineReducers
函数
注意:
合并后,Redux 的状态会变为一个对象,对象的结构与 combineReducers 函数的参数结构相同
{ a: aReducer 处理的状态, b: bReducer 处理的状态 }
import { combineReducers } from 'redux'
// 计数器案例,状态默认值为:0
const aReducer = (state = 0, action) => {}
// Todos 案例,状态默认值为:[]
const bReducer = (state = [], action) => {}
// 合并多个 reducer 为一个 根reducer
const rootReducer = combineReducers({
a: aReducer,
b: bReducer
})
// 创建 store 时,传入 根reducer
const store = createStore(rootReducer)
// 此时,合并后的 redux 状态: { a: 0, b: [] }
注意:虽然在使用combineReducers
以后,整个 Redux 应用的状态变为了对象
,但是,对于每个 reducer 来说,每个 reducer 只负责整个状态中的某一个值
loginReducer
处理的状态只应该是跟登录相关的状态profileReducer
处理的状态只应该是跟个人资料相关的状态不同状态的处理方式:
!评论内容需包含中文