react中的redux(全局通信)的两种方式
1. redux介绍
1.1 Redux 是React最常用的集中状态管理工具,类似于Vue中的Pinia(Vuex)。
1.2 redux数据流框架
注意:浏览器最好使用Google Chrome,浏览器中先安装一个插件(Redux DevTools)。
2. 早期redux版本(代码为主)
1. 所需的包
redux、redux-thunk(异步操作)、redux-devtools-extension、react-redux。
npm 依赖冲突的话,请加 - - force
2.文件结构
3. 代码详解
index.js文件(程序入口)
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App'; //引入App.js
//下面两行与redux有关,第一个是引入Provider,第二个是引入已经创建好的store
import { Provider } from 'react-redux';
import store from './redux/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
App.js文件
import Operation from './components/operation'
import Show from './components/show'
function App() {
return (
<div >
<Operation />
<hr/>
<Show />
</div>
);
}
export default App;
components文件夹下的文件
operation.js 文件
import { useState } from "react"
//将operation.js中的状态与redux中的状态绑定
import { connect } from "react-redux"
//引入operationAction中的方法,两个
import { incrementPerson, decrementPerson } from "../redux/actions/operationAction"
const Operation = (props) => {
//通过props获取已经绑定好的状态和方法
let {persons, incrementPerson, decrementPerson} = props
const [id, setId] = useState("");
const [name, setName] = useState("");
return (
<div className="operation">
请输入id号: <input type="input" value={id} onChange={(e) => setId(e.target.value)} /> <br />
请输入姓名: <input type="input" value={name} onChange={(e) => setName(e.target.value)} /><br />
<button onClick={() => {incrementPerson({id: id, name: name})}}>添加</button>
<button onClick={() => {decrementPerson({id: id, name: name})}}>删除</button>
</div>
);
}
//绑定状态和方法
//incrementPerson ---> incrementPerson : incrementPerson
//decrementPerson ---> decrementPerson : decrementPerson
export default connect(
(state) => ({
persons: state.OperationReducer.persons
}),
{
incrementPerson,
decrementPerson
}
)(Operation);
show.js文件
import {connect} from 'react-redux'
const Show = (props) =>{
let {persons} = props;
return(
<div>
{
persons.map((item,index) =>{
return(
<li key={index}>
{`id: ${item.id}, name: ${item.name}`}
</li>
)
})
}
</div>
);
}
export default connect(
(state) =>({
persons: state.OperationReducer.persons
})
)(Show);
redux文件夹中的文件
constant.js
//定义一些常量,并向外面暴露,这样可以预防字符串反复写错
export const INCREMENT_PERSON = 'increment_person'
export const DECREMENT_PERSON = 'decrement_person'
/actions/operationAction.js
import {INCREMENT_PERSON, DECREMENT_PERSON} from '../constant'
//定义了action的各种类型和传入的数据
// data -----> data: data
export const incrementPerson = data => ({type: INCREMENT_PERSON, data})
export const decrementPerson = data => ({type: DECREMENT_PERSON, data})
/reducers/operationReducer.js
import {INCREMENT_PERSON, DECREMENT_PERSON} from '../constant'
//这里定义了初始状态
const initState = {
persons: [
{id: 1, name: '张三'}
]
}
//对状态进行更改操作,这里返回的对象一定要是深拷贝,不能是浅拷贝。
export default function operationReducer(state = initState, action) {
const {type,data} = action
const {persons} = state
switch (type){
case INCREMENT_PERSON:
return {persons: [...persons, data]}
case DECREMENT_PERSON:
return {persons: persons.filter(item => item.id !== data.id && item.name !== data.name)}
default:
return state
}
}
/reducers/index.js
import {combineReducers} from 'redux'
import OperationReducer from './operationReducer'
//用来合并reducers,当有多个reducer的时候,这里直接统一合并然后暴露给store
export default combineReducers({
OperationReducer
})
store.js
import {legacy_createStore,applyMiddleware} from "redux"
import {thunk} from "redux-thunk"
import allReducers from "./reducers"
import {composeWithDevTools} from "redux-devtools-extension"
// 加入了Google中的redux插件,创建store
export default legacy_createStore(allReducers,composeWithDevTools(applyMiddleware(thunk)))
// 没有加入Google中的redux插件
// export default legacy_createStore(allReducers,applyMiddleware(thunk))
4. 运行效果
-
初始状态
-
添加
-
删除
3. react18版本中模块化的redux
1. 所需的包
@reduxjs/toolkit
react-redux
这两个包,缺一不可。
2. 文件结构
3. 代码详解
index.js文件(程序入口)
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
//redux相关的文件
import { Provider } from 'react-redux';
import store from './store'; //注意,这里还是引入store
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
App.js文件
import Operation from './components/operation'
import Show from './components/show'
function App() {
return (
<div >
<Operation />
<hr/>
<Show />
</div>
);
}
export default App;
components文件夹下的文件
operation.js 文件
import { useState } from "react"
import {useDispatch } from "react-redux";
//导入actionCreater
import {incrementPerson, decrementPerson} from '../store/modules/personsStore'
import {fetchChannelList} from '../store/modules/channelStore'
const Operation = () => {
const [id, setId] = useState("");
const [name, setName] = useState("");
const dispatch = useDispatch();
return (
<div className="operation">
请输入id号: <input type="input" value={id} onChange={(e) => setId(e.target.value)} /> <br />
请输入姓名: <input type="input" value={name} onChange={(e) => setName(e.target.value)} /><br />
<button onClick={() => {dispatch(incrementPerson({id:id,name:name}))}}>添加</button>
<button onClick={() => {dispatch(decrementPerson({id:id,name:name}))}}>删除</button>
<button onClick={() => {dispatch(fetchChannelList())}}>异步操作</button>
</div>
);
}
export default Operation;
show.js 文件
import { useSelector } from "react-redux";
const Show = () =>{
//这里是获取redux中的状态,对象解构
const {personList} = useSelector(state => state.persons)
return(
<div>
{personList.map((person,index) =>{
return <li key={index}>{`id: ${person.id} name: ${person.name}`}</li>
})}
</div>
);
}
export default Show;
store文件夹中的文件
modules/personsStore.js
import { createSlice} from "@reduxjs/toolkit"
const personsStore = createSlice({
//命名空间
name: 'persons',
//初始对象
initialState: {
personList: [{
id: "1",
name: "张三"
}]
},
reducers: {
incrementPerson(state,action){
state.personList.push(action.payload)
},
decrementPerson(state,action){
let data = action.payload
state.personList = state.personList.filter(person => person.id !== data.id && person.name !== data.name)
}
}
})
//解构出来actionCreater函数
const { incrementPerson,decrementPerson } = personsStore.actions
//获取reducer
const reducer = personsStore.reducer
//以按需导出的方式导出actionCreater函数
export { incrementPerson,decrementPerson}
//以默认导出的方式导出reducer
export default reducer
modules/channelStore.js
import {createSlice} from '@reduxjs/toolkit'
import axios from 'axios'
const channelStore = createSlice({
//命名空间
name: 'channel',
// 初始状态
initialState: {
channelList: []
},
reducers:{
setChannelList(state,action){
state.channelList = action.payload
}
}
})
//异步请求部分
const { setChannelList } = channelStore.actions
const fetchChannelList = () => {
return async(dispatch) =>{
const res = await axios.get('http://geek.itheima.net/v1_0/channels')
dispatch(setChannelList(res.data.data.channels))
}
}
export {fetchChannelList}
export default channelStore.reducer
store文件夹中的index.js文件
import { configureStore } from '@reduxjs/toolkit'
//导入子模块reducer
import personsReducer from './modules/personsStore'
import channelReducer from './modules/channelStore'
//这里的persons 与 channel 名字决定了后面调用useSelector的状态的名字
//例如const {personList} = useSelector(state => state.persons)
const store = configureStore({
reducer: {
persons: personsReducer,
channel: channelReducer
}
})
export default store
4. 运行效果
-
初始状态
-
添加
-
删除
-
异步操作
注意:这里axios访问的链接后面可能会过期,如果过期了,自己新创一个链接访问就行。