一、redux是什么
1.redux是一个专门用于做状态管理的js库
2.可以不和任何框架绑定单独使用,也可以用在js、react、vue等项目中,但基本与react配合使用
3.作用:集中式管理react应用中多个组件共享的状态
二、什么情况下需要使用redux
1.某个组件的状态,需要让其他组件可以随时拿到(共享)
2.一个组件需要改变另一个组件的状态(通信)
3.总体原则:能不用就不用,如果不用比较吃力才考虑使用
三、redux工作流程
解释:
1.在react components(用户)中明确自身要执行什么操作,会被action creators(外卖平台)识别到
2.action动作对象,包含动作类型和本次要操作的数据,dispatch()分发下去交由别人执行这个动作
3.store指挥官(商家),reducers真正执行动作的(厨师),指挥官将previousState之前的数据和执行的动作交于厨师,厨师再告诉指挥官结果
4.最后在react components中调用getState()知道结果
5.reducers不仅能加工状态,也能初始化状态,初始化时type值不为我所定义的任何type,是内置的,此时data和previousState为undefined
四、三个核心概念
action
1.动作的对象
2.包含两个属性:
type:标识属性,值为字符串。唯一,必要属性
data:数据睡醒,值类型任意,可选属性
reducer
1.用于初始化状态、加工状态
2.加工时,根据旧的state和action,产生新的state的纯函数
store
1.将state、action、reducer联系在一起的对象
2.如何得到此对象?
1.import {createStore} from 'redux' 2.import reducer from './reducers' 3.const store = createStore(reducer)
3.此对象的功能
1.getState():得到state 2.dispatch(action):分发action,触发reducer调用,产生新的state 3.subscribe(listener):注册监听,当产生了新的state时,自动调用
五、redux 的使用流程
以点击按钮实现数字的加减为例
github:https://github.com/Mrs-Lupin/react-redux-pro.git
1.安装配套工具
npm i @reduxjs/toolkit react-redux
2.创建modules文件夹下的某一功能store部分
src/store/modules/countStore.js
//引入创建store方法
import { createSlice } from '@reduxjs/toolkit'
const counterStore = createSlice({
name: 'counter',
//初始化状态数据
initialState: {
count: 0
},
//修改数据的同步方法
reducers: {
//这里写的都是actionCreater
increment(state) {
state.count++
},
decrement(state) {
state.count--
},
//第一个参数state:当前的状态对象,第二个参数action:在调用actionCreater时候传递参数,参数会被传递到action对象payload属性上
addToNum(state,action){
state.count=action.payload
}
}
})
//解构出创建action对象的函数 (actionCreater)
const { increment, decrement, addToNum } = counterStore.actions
//按需导出创建action对象的函数
export { increment, decrement, addToNum }
//获取reducer函数
const reducer = counterStore.reducer
//默认导出reducer函数
export default reducer
3.集成组合到根store下
src/store/index.js
//导入组合方法
import { configureStore } from '@reduxjs/toolkit'
//导入子模块reducer
import counterReducer from './modules/counterStore'
//创建根store组合子模块
const store = configureStore({
reducer: {
counter: counterReducer
}
})
export default store
4.使用react-redux将redux和react连接,将store注入到react中
src/index.js
import React from 'react'
import { createRoot } from 'react-dom/client'
//导入store
import store from './store'
//导入Provider组件
import { Provider } from 'react-redux'
import App from './App'
const root = createRoot(document.getElementById('root'))
root.render(
//通过store参数将创建好的store实例注入到应用中,链接正式成立
<Provider store={store}>
<App />
</Provider>
)
5.在组件中获取并使用store中的数据---useSelector
src/App.js
//通过useSelector找到想要的状态,并从中解构出想要的数据
const {count} = useSelector(state => state.counter)
//这里写的counter就是src/store/index.js中reducer下的counter
6.在组件中修改store中的数据---useDispatch:生成提交action对象的dispatch函数
src/App.js
//导入useDispatch方法
import { useDispatch } from 'react-redux'
//导入actionCreater
import { decrement,addToNum } from './store/modules/counterStore'
function App() {
const dispatch = useDispatch()
return (
<div className="App">/
//绑定一个事件,dispatch一个action对象
<button onClick={() => dispatch(decrement())}>-</button>
//传递参数
<button onClick={() => dispatch(addToNum(10))}>add to 10</button>
);
}
export default App;
7.处理异步操作
以渲染一个列表为例
(1)创建store的写法保持不变,配置好同步修改状态的方法
src/store/modules/channelStore.js
import { createSlice } from "@reduxjs/toolkit";
import axios from 'axios'
const channelStore = createSlice({
name: 'channel',
initialState: {
channelList: []
},
reducers: {
setChannels(state, action) {
state.channelList = action.payload
}
}
})
const reducer = channelStore.reducer
export default reducer
(2)单独封装一个函数,在函数内部return一个新函数,在新函数中
-
封装异步请求获取数据
-
调用同步actionCreater传入异步数据生成一个action对象,并使用dispatch提交
src/store/modules/channelStore.js
//异步请求部分
const { setChannels } = channelStore.actions
const fetchChannelList = () => {
return async (dispatch) => {
const res = await axios.get('http://geek.itheima.net/v1_0/channels')
dispatch(setChannels(res.data.data.channels))
}
}
export { fetchChannelList }
(3)组件中dispatch的写法保持不变
import { useDispatch, useSelector } from 'react-redux'
//导入actionCreater
import { fetchChannelList } from './store/modules/channelStore'
//导入hook函数
import { useEffect } from 'react'
function App() {
const { channelList } = useSelector(store => store.channel)
const dispatch = useDispatch()
//使用useEffect触发异步请求执行
useEffect(() => {
//初始化渲染列表
dispatch(fetchChannelList())
//依赖项为dispatch只执行一次
}, [dispatch])
return (
<div className="App">
<ul>
{channelList.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
</div>
);
}
export default App;