前端学习--React(3)

news2024/9/27 5:57:35

一、Redux

集中状态管理工具,不需要react即可使用,每个store的数据都是独立于组件之外的

vue小链接:vuex/pinia

基本使用

Redux将数据修改流程分成三个概念,state、action和reducer

state - 一个对象 存放我们管理的数据状态

action - 一个对象 描述你如何修改数据

reducer - 一个函数 根据action的描述生成新的state

<button id="decrement">-</button>
<span id="count">0</span>
<button id="increment">+</button>

<script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>

<script>
  // 1. 定义reducer函数 
  // 作用: 根据不同的action对象,返回不同的新的state
  // state: 管理的数据初始状态
  // action: 对象 type 标记当前想要做什么样的修改
  function reducer (state = { count: 0 }, action) {
    // 数据不可变:基于原始状态生成一个新的状态 所以要返回新对象
    if (action.type === 'INCREMENT') {
      return { count: state.count + 1 }
    }
    if (action.type === 'DECREMENT') {
      return { count: state.count - 1 }
    }
    return state
  }

  // 2. 使用reducer函数生成store实例
  const store = Redux.createStore(reducer)

  // 3. 通过store实例的subscribe订阅数据变化
  // 回调函数可以在每次state发生变化的时候自动执行
  store.subscribe(() => {
    console.log('state变化了', store.getState())
    document.getElementById('count').innerText = store.getState().count
  })

  // 4. 通过store实例的dispatch函数提交action更改状态 
  const inBtn = document.getElementById('increment')
  inBtn.addEventListener('click', () => {
    // 增
    store.dispatch({
      type: 'INCREMENT'
    })
  })

  const dBtn = document.getElementById('decrement')
  dBtn.addEventListener('click', () => {
    // 减
    store.dispatch({
      type: 'DECREMENT'
    })
  })

  // 5. 通过store实例的getState方法获取最新状态更新到视图中

</script>

react中使用redux

相关工具

Redux Toolkit 简化redux书写逻辑

react-redux 链接Redux和React的中间件

npm i @reduxjs/toolkit react-redux

 安装成功

目录创建

创建src/store,modules存放子模块

counterStore.js

//1 导入并创建store
import {createSlice} from "@reduxjs/toolkit"

const counterStore = createSlice({
    name:'counter',
    // 初始状态
    initialState:{
        count:0
    },
    // 更新状态的方法
    reducers:{
        inscrement(state){
            state.count++
        },
        descrement(state){
            state.count --
        }
    }
})

const {inscrement, descrement} = counterStore.actions
const reducer = counterStore.reducer

export{
    inscrement,
    descrement
}

export default reducer

store/index.js

集成store/modules中所有子模块

import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./modules/counterStore"

// 将子模块中的所有store合成一个根store方便访问
const store = configureStore({
    reducer:{
        counter:counterReducer,
    }
})

export default store

src/index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import store from "./store"
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  // 通过react-redux提供的Provider 给组件注入store 使得redux定义的store能够被react组件使用
  <Provider store={store}>
    <App />
  </Provider>
);

App.js

useDispatch() 通过这个来派发reducer修改状态

import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement} from "./store/modules/counterStore"
function App() {
  const { count } = useSelector(state => state.counter)
  const dispatch = useDispatch()
  return (
    <div className="App">
      <button onClick={() => dispatch(inscrement())}>+</button>
      {count}
      <button onClick={() => dispatch(descrement())}>-</button>
    </div>
  );
}

export default App;

然后就完成了:

进阶版-提交action时传参

counterStore.js

增加了一个addToNum函数

//1 导入并创建store
import {createSlice} from "@reduxjs/toolkit"

const counterStore = createSlice({
    name:'counter',
    // 初始状态
    initialState:{
        count:0
    },
    // 更新状态的方法
    reducers:{
        inscrement(state){
            state.count++
        },
        descrement(state){
            state.count --
        },
        addToNum(state, action){
            // dispatch调用该方法时传入的参数就存放在action.payload
            state.count += action.payload
        }
    }
})

const {inscrement, descrement, addToNum} = counterStore.actions
const reducer = counterStore.reducer

export{
    inscrement,
    descrement,
    addToNum
}

export default reducer

 App.js

增加了两个值,传入不同参数

import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement, addToNum} from "./store/modules/counterStore"
function App() {
  const { count } = useSelector(state => state.counter)
  const dispatch = useDispatch()
  return (
    <div className="App">
      <button onClick={() => dispatch(inscrement())}>+</button>
      {count}
      <button onClick={() => dispatch(descrement())}>-</button>
      <button onClick={() => dispatch(addToNum(10))}>+ 10</button>
      <button onClick={() => dispatch(addToNum(-10))}>- 10</button>
    </div>
  );
}

export default App;

再进阶版-异步状态操作

channelStore.js

import {createSlice} from '@reduxjs/toolkit'
import axios from 'axios'

const channelStore = createSlice({
    name:'channel',
    initialState:{
        channelList:[]
    },
    reducers:{
        getChannels(state, action){
            state.channelList = action.payload
        }
    }
})

const {getChannels} = channelStore.actions


//单独写一个异步action的函数 异步操作处理完毕后再调用同步action修改状态
const getChannelList = () => {
    return async(dispatch) => {
        const res = await axios.get('http://geek.itheima.net/v1_0/channels')
        dispatch(getChannels(res.data.data.channels))
    }
}

export {getChannelList}

const reducer = channelStore.reducer
export default reducer

 App.js

import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement, addToNum} from "./store/modules/counterStore"
import {getChannelList} from "./store/modules/channelStore"
import {useEffect} from 'react'
function App() {
  const { count } = useSelector(state => state.counter)
  const { channelList } = useSelector(state => state.channel)
  const dispatch = useDispatch()

  useEffect(()=> {
    dispatch(getChannelList())
  }, [dispatch])
  
  return (
    <div className="App">
      <button onClick={() => dispatch(inscrement())}>+</button>
      {count}
      <button onClick={() => dispatch(descrement())}>-</button>
      <button onClick={() => dispatch(addToNum(10))}>+ 10</button>
      <button onClick={() => dispatch(addToNum(-10))}>- 10</button>
      <ul>
        {channelList.map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
    </div>
  );
}

export default App;

调试工具redux devtools

直接在chorme商店里下载

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1243341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EI论文故障识别程序:DBN深度置信/信念网络的故障识别Matlab程序,数据由Excel导入,直接运行!

​适用平台&#xff1a;Matlab2021b版及以上 本程序参考中文EI期刊《基于变分模态分解和改进灰狼算法优化深度置信网络的自动转换开关故障识别》中的深度置信网络&#xff08;Deep Belief Network&#xff0c;DBN&#xff09;部分进行故障识别&#xff0c;程序注释清晰&#x…

OpenStack云计算平台-Networking 服务

目录 一、网络服务概览 二、网络&#xff08;neutron&#xff09;概念 三、安装并配置控制节点 1、先决条件 2、配置网络选项&#xff08;公共网络&#xff09; &#xff08;1&#xff09;安装组件 &#xff08;2&#xff09;配置服务组件 &#xff08;3&#xff09;配…

Notepad-- ubuntu下载安装

Notepad-- ubuntu下载安装 下载 Gitee链接&#xff1a; https://gitee.com/cxasm/notepad– 安装 sudo apt install *.deb运行 /opt/apps/com.hmja.notepad/files/Notepad--出错 需要安装qt5 sudo apt-get install qt5-default

【UE】用样条线实现测距功能(下)

目录 效果 步骤 一、实现多次测距功能 二、通过控件蓝图来进行测距 在上一篇&#xff08;【UE】用样条线实现测距功能&#xff08;上&#xff09;&#xff09;文章基础上继续实现多次测距和清除功能。 效果 步骤 一、实现多次测距功能 打开蓝图“BP_Spline”&#xff0c…

UML建模图文详解教程05——包图

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl本文参考资料&#xff1a;《UML面向对象分析、建模与设计&#xff08;第2版&#xff09;》吕云翔&#xff0c;赵天宇 著 包图概述 包图(package diagram)是用来描述模型中的…

DAOS低时延与高性能RDMA网络

什么是RDMA RDMA&#xff08;Remote Direct Memory Access&#xff09;远程直接内存访问是一种技术&#xff0c;它使两台联网的计算机能够在主内存中交换数据&#xff0c;而无需依赖任何一台计算机的处理器、缓存或操作系统。与基于本地的直接内存访问 ( DMA ) 一样&#xff0c…

抖音本地生活服务商申请怎么做?无保证金的申请方法来了

想做抖音的本地生活服务项目&#xff0c;却不知道去哪里申请&#xff0c;或者如何申请&#xff0c;其实&#xff0c;官方的通道在今年上半年还是有的&#xff0c;自己去平台上提交资料申请就可以了&#xff0c;但需要缴纳高额的保证金。 而在今年下半年&#xff0c;平台已经关…

SPS简单对应分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

【算法】经典算法题

文章目录 专题一&#xff1a;双指针1. 移动零2. 复写零3. 快乐数4. 盛最多水的容器5. 有效三角形的个数6. 查找总价格为目标值的两个商品7. 三数之和8. 四数之和 专题二&#xff1a;滑动窗口1. 长度最小的子数组2. 无重复字符的最长字串3. 最大连续1的个数 III4. 将 x 减到 0 的…

【尚跑】2023泾阳半程马拉松144 PB完赛

1、赛事背景 来到泾阳&#xff0c;就来到了中国大地原点&#xff1b; 来到泾阳&#xff0c;就来到了陕西的“白菜心心”&#xff1b; 来到泾阳&#xff0c;就来到了具有2000多年的历史长河&#xff1b; 泾河水缓缓流&#xff0c;流过郑国渠&#xff1b; 泾河水缓缓流&…

线程提交线程到线程池,有几种方式,哪一种方式是工作中不能使用的,无法捕捉异常,线程池的拒绝策略,线程池的提交方式

线程池的工作原理 JDK中提交线程到线程池&#xff0c;有几种方式&#xff0c;哪一种方式是工作中不能使用的&#xff0c;无法捕捉异常 两种提交任务的方法 ExecutorService 提供了两种提交任务的方法&#xff1a; execute()&#xff1a;提交不需要返回值的任务 submit()&a…

gRPC之gRPC负载均衡(客户端负载均衡)(etcd)

1、gRPC负载均衡(客户端负载均衡)(etcd) 本篇将基于etcd的服务发现前提下&#xff0c;介绍如何实现gRPC客户端负载均衡。 1.1 gRPC负载均衡 gRPC官方文档提供了关于gRPC负载均衡方案Load Balancing in gRPC https://github.com/grpc/grpc/blob/master/doc/load-balancing.m…

二十一、文档操作

目录 一、添加文档 1、编写代码 2、运行并查看 二、查询文档 1、编写代码 2、运行并查看 三、删除文档 1、编写代码 2、运行并查看 四、修改文档 方式一&#xff1a;全量修改&#xff0c;会删除旧文档&#xff0c;添加新文档 方式二&#xff1a;局部修改。增量修改&…

TCP /UDP协议的 socket 调用的过程

在传输层有两个主流的协议 TCP 和 UDP&#xff0c;socket 程序设计也是主要操作这两个协议。这两个协议的区别是什么呢&#xff1f;通常的答案是下面这样的。 TCP 是面向连接的&#xff0c;UDP 是面向无连接的。TCP 提供可靠交付&#xff0c;无差错、不丢失、不重复、并且按序…

mybatis 语法使用各种踩坑(持续更新中。。。)

1、大小写命名&#xff1a;这个别说了&#xff0c;都是泪。 2、联表查询查询&#xff0c;多条合成一条&#xff0c;不生效的原因 博主各种检查关联关系和字段大小写&#xff0c;本来是4条数据最后合成一条数据&#xff0c;死活给你直接返回了4条数据&#xff0c;而且每个类似p…

实现二叉搜索树的查找、插入和删除功能(思路+图文+代码详解)

文章目录 二叉搜索树一、搜索树1.二叉搜索树的查找2.二叉搜索树的插入3.二叉搜索树的删除4.性能分析 二叉搜索树 HashMap和HashSet的底层是一个哈希表 TreeMap 和TreeSet底层是一棵搜索树&#xff08;红黑树&#xff09; 涉及到一些搜索查找的场景可以调用Map和Set接口 一、…

SPSS多元对应分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

IDEA、PHPSTORM 在命令行中进行 PHP debug

然在终端执行控制器的方法php yii test/ab 即可看到触发debug 调试

管理类联考——英语二——备考 100 句涵盖所有词汇

全中 在海里的这个地区&#xff0c;熊猫们喜欢就着苏打碗豆喝茶。而大洋州的民兵则喜欢经过半岛&#xff0c;带着编剧本的公式上餐厅去。附件的电影院里有额外的歌剧和香蕉&#xff0c;这一时代的斑马们被外面的天线所吸引。实验室里的蟹想用它的肋骨去戳四肢象灯炮的小羊。但…