环境准备
我们都知道单独使用redux来进行react开发是挺复杂的,如今在React中使用redux,官方推荐安装俩个其他插件 Redux Toolkit 和 react-redux。
- Redux Toolkit(RTK)- 官方推荐编写Redux逻辑的方式,是一套工具的集合集,简化书写方式。
- react-redux - 用来 链接 Redux 和 React组件 的中间件
进行下载
npm i @reduxjs/toolkit react-redux
同时为了规范编码我们一般会创建一个store文件夹来进行管理,应用通常会有很多个子store模块,所以创建一个moudle目录,在内部编写业务分类的子store。同时创建store中的入口文件 index.js ,作用是组合modules中所有的子模块,并导出store。
使用React Toolkit 创建 Store
本文采用一个计数器和一个数据展示的例子来进行编码,
- 计数器展示数据 并对数据进行加减操作
- 数据展示 用异步action来展示数据
首先创建计数器的store
// 引入createSlice来进行创建store
import { createSlice } from '@reduxjs/toolkit'
const countStore = createSlice({
name: 'count',
// 初始化state
initialState: {
count: 1,
},
// 修改状态的方法 支持直接修改
reducers: {
add(state, action) {
state.count += action.payload
},
sub(state, action) {
state.count -= action.payload
},
},
})
// 解构出action
const { add, sub } = countStore.actions
// 获取reducer
const reducer = countStore.reducer
// 导出action 和 reducer
export { add, sub }
export default reducer
在index.js进行引入
// 引入configureStore
import { configureStore } from '@reduxjs/toolkit'
// 导入子模块reducer
import countReducer from './moudle/countStore'
const stores = configureStore({
reducer: {
count: countReducer,
}
})
export default stores
configureStore是reduxjs/toolkit中的一个函数,用于创建Redux store。使用configureStore可以简化store的创建过程,并提供一些默认配置。它接受一个包含多个配置选项的对象作为参数,这些选项包括:
- reducer:reducer函数,用于处理store中的状态更新。
- middleware:中间件函数,用于处理store中的action。
- devTools:用于开发环境的调试工具的配置选项。
- preloadedState:store的初始状态。
为React注入store
现在我们搭建的contStore已经完成了,现在我们使用react-redu来把Redux和React 链接 起来,内置 Provider组件 通过 store 参数把创建好的store实例注入到应用中,链接正式建立。
打开项目的入口文件
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
// 引入 stores
import stores from './store'
// 引入Provide组件
import { Provider } from 'react-redux'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
// store参数把创建好的store实例注入到应用中,使所有组件都可操作store
<Provider store={stores}>
<App />
</Provider>
</React.StrictMode>
)
在组件中使用
至此我们已经完成的count的store的搭建,现在我们来在组件中使用并更改store的数据。在此我们要知道两个钩子来对store的数据进行操作。
- 在React组件中使用store中的数据,需要用到一个钩子函数 - useSelector,它的作用是把store中的数据映射到组件中
- React组件中修改store中的数据需要借助另外一个hook函数 - useDispatch,它的作用是生成提交action对象的dispatch函数
具体实现
import React from 'react'
// 引入相应hook函数
import { useSelector, useDispatch } from 'react-redux'
// 引入方法
import { add, sub } from './store/moudle/countStore'
export default function App() {
// 获取store数据
const { count } = useSelector((state) => state.count)
const dispatch = useDispatch()
return (
<div>
<h2>计数组件</h2>
<div>
<button onClick={() => dispatch(sub(2))}>点击减2</button>
<b>{count}</b>
<button onClick={() => dispatch(add(3))}>点击加3</button>
</div>
</div>
)
}
结果如图
Redux与React - 异步action处理
我们按照步骤重新创建一个关于数据列表的store
单独封装一个函数,
在函数内部return一个新函数
在新函数中封装异步请求获取数据
调用同步actionCreater传入异步数据生成一个action对象,并使用dispatch提交
import { createSlice } from '@reduxjs/toolkit'
import axios from 'axios'
const channelStore = createSlice({
name: 'channel',
initialState: {
channelList: [],
},
reducers: {
setChannel(state, action) {
state.channelList = action.payload
},
},
})
// 异步请求部分
const { setChannel } = channelStore.actions
const reducer = channelStore.reducer
const fecthChannelList = () => {
return async (dispatch) => {
const { data } = await axios.get('http://geek.itheima.net/v1_0/channels')
dispatch(setChannel(data.data.channels))
}
}
export { fecthChannelList }
export default reducer
别忘了在store文件夹的index.js文件中添加channleSore
import { configureStore } from '@reduxjs/toolkit'
// 导入子模块reducer
import countReducer from './moudle/countStore'
import channelReducer from './moudle/channelStore'
const stores = configureStore({
reducer: {
count: countReducer,
channels:channelReducer
}
})
export default stores
组件中使用
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { fecthChannelList } from './store/moudle/channelStore'
export default function Channel() {
const { channelList } = useSelector((state) => state.channels)
const dispatch = useDispatch()
// 在useEffect函数中调用
useEffect(() => {
dispatch(fecthChannelList())
}, [dispatch])
return (
<div>
<h2>数据展示</h2>
<ul>
{channelList.map((item) => (<li key={item.id}>{item.name}</li>))}
</ul>
</div>
)
}