react中的redux的两种方式

react中的redux(全局通信)的两种方式

1. redux介绍

1.1 Redux 是React最常用的集中状态管理工具,类似于Vue中的Pinia(Vuex)。

1

1.2 redux数据流框架

3

注意:浏览器最好使用Google Chrome,浏览器中先安装一个插件(Redux DevTools)。

image-20240425142445655

2. 早期redux版本(代码为主)

1. 所需的包

redux、redux-thunk(异步操作)、redux-devtools-extension、react-redux。

npm 依赖冲突的话,请加 - - force

2.文件结构

image-20240425142637439

image-20240425143240940

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>&nbsp;&nbsp;&nbsp;&nbsp;
      <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. 运行效果
  1. 初始状态

    image-20240425150747709


  2. 添加

image-20240425150822700


  1. 删除

    image-20240425150922301


3. react18版本中模块化的redux

1. 所需的包

@reduxjs/toolkit
react-redux

这两个包,缺一不可。

2. 文件结构

image-20240425164732619

image-20240425165148088

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>&nbsp;&nbsp;&nbsp;&nbsp;
      <button onClick={() => {dispatch(decrementPerson({id:id,name:name}))}}>删除</button>&nbsp;&nbsp;&nbsp;&nbsp;
      <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. 运行效果
  1. 初始状态

    image-20240425170255032


  2. 添加

    image-20240425170407099


  3. 删除

    image-20240425170515235


  4. 异步操作

    image-20240425170651474


注意:这里axios访问的链接后面可能会过期,如果过期了,自己新创一个链接访问就行。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值