前言
在当今我们 Web 项目开发中,构建绚丽又庞大的前端应用程序已经成为了常态,而伴随来就是项目渐渐复杂。在项目中,我们需要处理大量的数据流,复杂的用户交互和公共状态管理。在这个背景下,React 给我伴生出了一款强大的状态管理器------ Redux。那接下来,我就来给小伙伴们探索探索 Redux 的用法。
介绍与核心概念
首先我们知道 Redux 是一个用于JavaScript应用程序状态管理的开源库。它是帮助我们更好的组织和管理应用程序的状态,使我们在仓库定义的状态的变化可以预测和调试。
Rudex的核心概念有四点:
-
单一数据源 : 我们的状态都被储存在一个单一的
Store
中,每个Store
的状态是不互通的,而且这些状态是只读的,不能直接的修改,我们只能通过发起一个描述变化的Action
来触发状态的修改。 -
状态是只读的 : Redux 不允许直接修改状态,如果想要改变某个状态,我们需要创建一个描述状态变化的
Reducer
纯粹函数,它可以接收当前状态和Action
作为参数,并且返回出一个新的状态,保持了状态的不可变性,并使得状态变化可追踪和调试。 -
使用纯粹函数进行状态修改 : 我们创建的
Reducer
是一个纯粹的函数, 它根据传入的Action类型和数据来计算新的状态,它不会产生任何副作用。 -
通过订阅和派发实现数据流 : 在项目中,我们需要通过调用
dispatch
方法并传递一个Action
来触发状态的变化。当状态发生变化时,所有订阅了Store的视图都会被通知到,并更新界面。这样就使我们的数据流变成了单向性的,使用中也就使数据变得更加的可控。
在介绍完上述四点核心概念之后,那下一步我们就在项目中将这四点核心概念给用上。
应用
首先我们来创建一个空的仓库,文件结构如下:
我们先建了一个index.js
作为我们整个仓库的出口,同时又在 modules
文件夹下贱了两个独立的空仓库。
我们先来看看我们的仓库出口代码是怎么写的:
javascript
import { configureStore } from '@reduxjs/toolkit'
import counterStore from './modules/couterStore'
import testStore from './modules/testStore'
export default configureStore({
reducer: {
counterStore,
testStore
}
})
从上述代码看出,我们使用了一个 configureStore
函数和纯粹函数来帮我们创建出了总体的Store
仓库,其中configureStore
函数还可以接收 middleware
等参数。
第二步,我们就来到了我们刚创建的coucouter.js
仓库中了,我们来往仓库加点东西,代码如下:
javascript
import { createSlice } from '@reduxjs/toolkit'
const counter = createSlice({
// 模块的名称,独一无二
name: 'counter',
// 初始数据
initialState: {
count: 1
},
// 定义用于修改数据源的方法
reducers: {
add(state) {
state.count++
}
}
})
const { add } = counter.actions
const reduer = counter.reducer
export { add }
export default reduer
我们创建了一个名为counter
的仓库, 我们往里面加入了名为count
的状态,接着,我们还定义了改变状态的add
方法,最后我们将方法和reducer
对象给抛出。
第三步,我们就该在项目中应用上仓库了,我们来一段这样的代码:
javascript
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { add } from '../../store/modules/couterStore'
export default function Counter() {
const { count } = useSelector(state => state.counterStore) // 拿到 counterStore分仓库
const disPatch = useDispatch()
const clickHandler = () => {
const action = add()
// 告诉sotore, 我要修改的数据源
disPatch(action)
}
return (
<div>
{count}
<button onClick={clickHandler}>add count</button>
</div>
)
}
想要在组件中使用仓库,首先我们使用useSelector
方法将该分仓库给拿出来,同时将我们需要的状态给解构出来,这样我们即可直接使用该状态。
那使用我们说完了,那接下来就该到修改了,修改我们则需要借助useDispatch
方法,并将修改状态的add
方法给拿。我们在组件定义了一个修改状态的clickHandler
事件,在其中调用了add
方法,最后调用disPatch
方法,同时将add
方法的返回值去派发数据流。这样我们才算完成了修改操作。
异步
经过这三步,我们就完成了仓库的应用,那最后我再来给小伙伴带来一段Redux
做异步请求数据的代码,感兴趣的小伙伴也可以去试试哦。
taskStore.js
仓库代码:
javascript
import { createSlice } from '@reduxjs/toolkit'
import axios from 'axios'
const test = createSlice({
// 模块的名称,独一无二
name: 'test',
// 初始数据
initialState: {
channels: []
},
// 定义用于修改数据源的方法
reducers: {
setChannels(state, action){
state.channels = action.payload
}
}
})
// 请求
const url = ''
// 该方法不是 action 方法,它只是一个请求数据并派发给仓库的函数方法,可以定义在组件里。
const fetchChannelList = () => {
return async (dispatch) =>{
const res = await axios.get(url)
dispatch(setChannels(res.data.data.channels))
}
}
const { setChannels } = test.actions
const reduer = test.reducer
export { setChannels, fetchChannelList }
export default reduer
在组件应用的组件代码:
javascript
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { addTaskList, fetchChannelList } from '../../store/modules/testStore'
export default function Task() {
const {channels } = useSelector(state => state.testStore)
const disPatch = useDispatch()
useEffect(() => {
const action = fetchChannelList()
// action(disPatch) //他们都是函数,所以这样也行
disPatch(action)
}, [disPatch])
return (
<div>
<ul>
{
channels.map(item => (
<li key={item.id}>{item.name}</li>
))
}
</ul>
</div>
)
}
如上述两份代码,我们就实现了在异步请求与仓库的联动,感兴趣的小伙伴快去试试吧。
总结
通过使用 Redux, 我们可以更好地管理项目的状态,同时还减少了状态管理的复杂性,帮我们更好的梳理复杂又庞大的项目逻辑。所以在具有具有复杂数据流和交互中大型项目中,我们应当更加倾向于使用 Redux 做我们的状态管理工具。同时 Redux 还提供了一些辅助工具和扩展,例如中间件(Middleware)、异步操作处理、时间旅行调试,感兴趣的小伙伴们可以自己去了解一下哦。