React笔记(八)Redux

这篇具有很好参考价值的文章主要介绍了React笔记(八)Redux。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、安装和配置

React 官方并没有提供对应的状态机插件,因此,我们需要下载第三方的状态机插件 —— Redux。

1、下载Redux

在终端中定位到项目根目录,然后执行以下命令下载 Redux

npm i redux
2、创建配置文件

在 React 中,不会自动生成状态机的相关配置代码,因此,需要我们自己手动去创建目录以及配置文件。

我们可以在 src 的目录中创建一个 reduxstore 的目录,用来存放所有关于状态机的配置文件。然后,在该目录中创建一个 store.js 文件,作为整个状态机的入口文件。

3、配置状态机
3.1、创建store仓库对象
import {legacy_createStore as createStore} from 'redux'
const store=createStore();
3.2、保存数据到store中

createStore 方法接收一个函数作为参数,该函数的返回值,会保存到 store 仓库中

const store = createStore((state = 数据初始值) => {
    return state;
});

通过函数参数的默认值的方式,来设置仓库数据的初始值

3.3、查看仓库数据

store 仓库对象身上,提供了一个 getState() 方法,用来查看仓库中的所有数据:

console.log(store.getState());

由于目前没有任何文件中在引入状态机的配置文件,如果我们需要查看仓库中的数据,暂时需要在 index.js 中引入 /redux/store.js 文件来让其运行。

二、Redux核心概念

1、Redux工作流程

React笔记(八)Redux,react.js,笔记,前端

2、Redux组成部分
2.1、state

state:状态,就是我们传递的数据

2.2、action

action是一个通知对象,里面必须有一个type属性,表示当前通知的类型,至于其他属性,你可以任意添加

可以通过store.dispatch(action对象)来更新仓库中的数据

注意:

  • 在实际开发中,更多人喜欢用action创建函数

  • 在实际开发中,大多数情况下,type会被定义成字符串常量

2.3、reducer

reducer本质是一个函数,它用来响应发送过来的actions,经过处理把state发送给store

  • 在reducer函数中,需要return返回值,这样store才能接收到数据

  • reducer函数接收两个参数,第一个参数是初始化store,第二个参数是action

React笔记(八)Redux,react.js,笔记,前端

2.4、store

数据仓库,存放组件数据的地方。一个项目一般只有一个数据仓库,store可以把action和reducer联系在一起。

主要的职责

  • 维护应用的state

  • 提供getState()方法获取state

  • 提供dispatch()方法发送action

  • 通过subscribe()来注册监听

  • 通过subscribe()返回值来注销监听

三、第一个Redux程序

1、创建action
  • 在src目录下创建一个actions文件夹

  • 在该目录下创建一个index.js文件

  • action是一个通知对象,里面必须有一个type属性,这里的num属性是自定义的表示计数器每次增加的个数

const incrementAction={
    type:'increment',
    num:1
}
export {incrementAction}
2、创建reducer
  • 在src目录下创建reducers目录

  • 在该目录下创建index.js文件,用来构建reducer,注意reducer要接收两个参数

  • 第一个参数是默认状态,我们可以定义一个初始化的state,然后进行赋值

  • 在函数里面判断第二个参数action的type值是否是我们发送过的,如果是,我们可以通过return返回新的state

const counterReducer=(state=0,action)=>{
   switch(action.type){
        case 'increment':
            return state+action.num
        default:
            return state
    }
}
export {counterReducer}
3、创建store
  • 在src目录下创建一个文件夹store

  • 在该目录下创建index.js文件,用来构建store,注意createStore函数第一个参数接收的是reducer

import {legacy_createStore as createStore} from 'redux'
import {counterReducer} from '../reducers'
const store=createStore(counterReducer)
export default store
4、在组件中使用
  • 创建components文件夹,该目录下存放自定义组件

  • 在该目录下新建Counter.jsx文件

  • 将Counter.jsx引入到App.js文件中

import Counter from "./components/Counter";
function App() {
  return (
    <div>
        <Counter></Counter>
    </div>
  );
}
export default App;
  • 调用dispatch函数,更新仓库的数据

import React,{useEffect,useState} from 'react'
import store from '../redux/store'
import {incrementAction} from '../redux/actions'

export default function Counter() {
  const increment=()=>{
      store.dispatch(incrementAction)
  }
  return (
    <div>
        <h1>计数器:{store.getState()}</h1>
        <button onClick={()=>{increment()}}>+</button>
    </div>
  )
}
  • 当组件加载完毕后,调用 store. subscribe注册监听,监听state数据的变化

import React,{useEffect,useState} from 'react'
import store from '../redux/store'
import {incrementAction} from '../redux/actions'

export default function Counter() {
  const [count, setCount] = useState(0);
  const increment=()=>{
      store.dispatch(incrementAction)
  }
  useEffect(()=>{
    store.subscribe(()=>{

        console.log('正在监控'+store.getState());
        setCount({})
    })
  })

  return (
    <div>
        <h1>计数器:{store.getState()}</h1>
        <button onClick={()=>{increment()}}>+</button>
    </div>
  )
}

四、redux中action和reducer的优化

1、action优化
1.1、action creator

我们一般会在页面里面修改数据,即,在页面里面调用store的dispatch方法。那就意味着action对象中的num字段很大可能是动态的,即不同的页面num字段可能是不同的,这样我们就不能把action写成一个死的对象,最好是封装成一个函数,执行过后返回一个action通知对象,然后num的值通过函数的参数来决定。这样的函数我们称之为action创建函数(action creator)

const incrementAction=(num)=>{
    return{
        type:'increment',
        num:num
    }
}
export {incrementAction}
1.2、type常量

在实际开发中,type在多数情况下会被定义成常量,如下所示

  • 在src/actions目录下,新建actionTypes.jsx文件,将所有type类型定义成常量

export const INCREMENT ="increment"
  • 在action creator中引入

import {INCREMENT} from './constant'
const incrementAction=(num)=>{
    return{
        type:INCREMENT,
        num:num
    }
}
export {incrementAction}
2、reducer优化

项目中肯定不止一个数据,所以state的默认值应该是一个对象,而不是其他。而且除了默认值,每当case到一个条件,返回一个新的对象时,应该返回一个全新的对象,然后才是你要修改的数据(当然这些数据,如果是引用类型的话,应该修改其引用本身,否则界面可能不会更新,尽管数据发生变化了

import { INCREMENT } from '../actions/constant'
const counterReducer = (state = { num: 0 }, action) => {
    switch (action.type) {
        case INCREMENT:
            return {
                ...state,
                num: state.num + action.num
            }
        default:
            return state
    }
}
export { counterReducer }

优化后,在组件中调用的代码如下

import React,{useEffect,useState} from 'react'
import store from '../redux/store'
import {incrementAction} from '../redux/actions'

export default function Counter() {
  const [count, setCount] = useState(0);
  const increment=()=>{
      store.dispatch(incrementAction(2))
  }
  useEffect(()=>{
    store.subscribe(()=>{

        console.log('正在监控'+store.getState());
        setCount({})
    })
  })

  return (
    <div>
        <h1>计数器:{store.getState()}</h1>
        <button onClick={()=>{increment()}}>+</button>
    </div>
  )
}

五、react-redux概述

为了方便使用,Redux 的作者封装了一个 React 专用的库 React-Redux,本文主要介绍它。

React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)。

1、UI组件

UI 组件有以下几个特征。

  • 只负责 UI 的呈现,不带有任何业务逻辑

  • 没有状态(即不使用this.state这个变量)

  • 所有数据都由参数(this.props)提供

  • 不使用任何 Redux 的 API

2、容器组件

容器组件有以下几个特征。

  • 负责管理数据和业务逻辑,不负责 UI 的呈现

  • 带有内部状态

  • 使用 Redux 的 API

总之,只要记住一句话就可以了:UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。

React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。

六、react-redux基本使用

1、安装react-redux
npm i react-redux
npm i redux
2、创建action
  • 在constant.jsx中添加INCREMENT

export const INCREMENT="increment";
  • 在src/actions/index.jsx中添加incrementAction

import { INCREMENT } from "./constant";
export const incrementAction=num=>({type:INCREMENT,num})
3、创建reducer
  • 在src/reducers/index.jsx中添加counterReducer

import {INCREMENT} from '../actions/constant'
const counterReducer=(state={num:0},action)=>{
    switch(action.type){
        case INCREMENT:
            return{
                ...state,
                num:state.num+action.num
            }
        default:
            return state
    }
}
export {counterReducer}
4、创建store

在src/store/index.jsx中编写代码如下

import {legacy_createStore as createStore} from 'redux'
import {counterReducer} from '../reducers'
const store=createStore(counterReducer)
export default store
5、全局注入store仓库
  • 在index.js中导入Provider组件

import {Provider} from 'react-redux'
  • 利用provider组件将整个接口进行包裹

  • 给Provider组件设置store的属性,该属性的值就是通过createStore构建出来的store实例对象

import ReactDOM from 'react-dom/client'
import App from './App';
import {Provider} from 'react-redux'
import store from './store'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
      <App />
    </Provider>
);
  • Provider在根组件外面包了一层,这样一来,App的所有子组件就默认都可以拿到state了。

6、组件关联仓库

由于UI组件不能使用Redux的API所以,如果在组件中如果要使用Redux就必须将UI组件变成容器类组件

React-Redux 提供connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来

import React from 'react'
import { connect } from 'react-redux'

function Counter() {
  render() {
    return (
      <div>
          
      </div>
    )
  }
}
export default connect()(Counter)
7、组件操作仓库
7.1、获取仓库数据

connect 方法接收一个回调函数作为参数:

const mapStateToProps = () => {

}
export default connect(mapStateToProps)(Counter);

该回调函数本身,又可以通过第一个参数接收到仓库中的所有数据

const mapStateToProps = (state) => {
    console.log(state); // 仓库中所有的数据
}
export default connect(mapStateToProps)(Counter);

在该回调函数中,返回一个对象,该对象会和组件的 props 进行合并。换句话说,该函数的返回值会添加到组件的 props 中:

const mapStateToProps = (state) => {
    return {
        数据名: 从 state 中获取的数据值
    }
}
export default connect(mapStateToProps)(Counter);

处理完成后,我们就可以在组件的 props 中访问到对应的仓库数据了:

function Counter(props)
    render() {
        return (
            <div>
                <h1>计数器</h1>
                <h2>{props.数据名}</h2>
            </div>
        )
    }
}
7.2、修改仓库数据

修改仓库数据,依然是通过 dispatch() 方法来触发修改操作。

在组件中,只要和仓库关联过,就能在 props 上直接获取到 dispatch 方法。因此,在组件中可以直接通过 props.dispatch() 方法来触发修改数据的操作。

import React,{useEffect,useState} from 'react'
import store from '../redux/store'
import {incrementAction} from '../redux/actions'
import { connect } from 'react-redux';

function Counter(props) {
  const increment=()=>{
      props.dispatch(incrementAction(3))
  }
  return (
    <div>
        <h1>计数器:{props.num}</h1>
        <button onClick={()=>{increment()}}>+</button>
    </div>
  )
}
const mapStateToProps = (state) => {
    console.log(state); // 仓库中所有的数据
    return{
       num:state.num
    }
}
export default connect(mapStateToProps)(Counter)

七、状态机的Hook

针对 React 中的函数组件,React-Redux 中也提供了第三方的 Hook。

1、useSelector

通过调用 useSelector 方法,并传递一个回调函数作为参数,我们可以在这个回调函数中获取到仓库中的 state。

import { useSelector } from 'react-redux'
useSelector((state) => {
    console.log(state);  // 仓库中所有的数据
})

然后我们可以在回调函数中,将我们需要使用的数据 return 出来,然后用一个变量来接收:

const data = useSelector((state) => {
    return 数据;
})

后续组件要使用数据,就可以直接通过变量进行数据的访问了。

2、useDispatch

调用 useDispatch() 方法,可以直接获取到 dispatch() 方法。

import { useDispatch } from 'react-redux'
export default fucntion Test() {
    const dispatch = useDispatch();
    return (
    )
}

如果组件中使用 Hook 来获取 dispatch 方法的话,就不再需要使用 connect 来对组件和仓库进行关联了。

获取到 dispatch 方法后,后续的使用就和 props.dispatch 的使用一致。

关键代码

import React from 'react'
import {useDispatch,useSelector} from 'react-redux'
import {incrementAction} from '../../redux/action'


export default function Counter(props) {
  const num=useSelector((state)=>{
    return state.num
  })
  const dispatch=useDispatch()
  const increment=()=>{
    dispatch(incrementAction(3))
  }
  return (
    <div>
        <h1>计数器:{num}</h1>
        <button onClick={()=>{increment()}}>+</button>
    </div>
  )
}

八、reducer拆分

当项目越来越大的时候,需要管理的数据也会越来越多,如果所有的数据都由一个reducer管理的话,则这个reducer肯定会变得非常的臃肿,且难以维护。所以有必要对reducer做一个拆分,不同功能模块的数据切片,由不同的reducer来管理。假设现在有两个模块,账户管理模块和商品管理模块,每个模块都有数据需要管理

import {combineReducers} from 'redux'
import counterReducer from './counterReducer'
export default combineReducers({
    counter:counterReducer
})

注意:调用时候需要使用使用到切片的名字才能访问到,比如文章来源地址https://www.toymoban.com/news/detail-694167.html

import React from 'react'
import {useSelector} from 'react-redux'
export default function Counter(props) {
  const count=useSelector((state)=>{
    console.log(state);
    return state.counter.num      //state.切片名的key.num
  })
  return (
    <div>
        <h1>计数器:{count}</h1>
    </div>
  )
}

到了这里,关于React笔记(八)Redux的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [尚硅谷React笔记]——第7章 redux

    目录: redux简介 redux工作流程 求和案例_纯react版 求和案例_redux精简版 redux完整版 异步action版 对react-redux的理解 连接容器组件与UI组件,react-redux基本使用 优化1_简写mapDispatch 优化2_Provider组件的使用 优化3_整合UI组件与容器组件 数据共享_编写Person组件,编写Person组件的reduc

    2024年02月06日
    浏览(36)
  • 【前端知识】React 基础巩固(三十二)——Redux的三大原则、使用流程及实践

    单一数据源 整个应用程序的state被存储在一颗object tree 中,并且这个object tree 只存储在一个store中; Redux并没有强制让我们不能创建多个Store,但是那样做不利于数据维护; 单一的数据源可以让整个应用程序的state变得方便维护、追踪、修改; State是只读的 唯一修改State的方法

    2024年02月15日
    浏览(62)
  • 【前端知识】React 基础巩固(三十一)——store数据的订阅和Redux的优化

    store/index.js test.js redux代码优化: 将派发的action生成过程放到一个actionCreators函数中 将定义的所有actionCreators的函数,放到一个独立的文件中:actionCreators.js actionCreators 和 reducer 函数中使用字符串常量是一致的,所以将常量抽取到一个独立的constants.js文件中 将reducer和默认值(

    2024年02月15日
    浏览(50)
  • React中使用Redux (二) - 通过react-redux库连接React和Redux

    react-redux库使用Redux 上一篇文章演示React中直接使用Redux的使用过程是十分繁琐的, 并且有许多重复代码 但是实际上redux官方帮助我们提供了 react-redux 的库,这个库是帮助我们完成连接redux和react的辅助工具, 可以直接在项目中使用,并且实现的逻辑会更加的严谨和高效 这篇我们

    2024年02月20日
    浏览(54)
  • 【React】redux和React-redux

    🎀个人主页:努力学习前端知识的小羊 感谢你们的支持:收藏🎄 点赞🍬 加关注🪐 redux 适用于多交互、多数据源的场景。 使用redux的场景: 某个组件的状态需要共享 一个组件需要改变其他组件的状态时 一个组件需要改变全局的状态时 redux的三大原则: 整个应用的 state

    2024年02月06日
    浏览(58)
  • 【React】React——redux

    🚩🚩🚩 💎个人主页: 阿选不出来 💨💨💨 💎个人简介: 一名大二在校生,学习方向前端,不定时更新自己学习道路上的一些笔记. 💨💨💨 💎目前开发的专栏: JS 🍭Vue🍭React🍭 💨💨💨 Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 redux是什么 redux是一个专门用于

    2024年01月15日
    浏览(48)
  • React中使用Redux (一) - 在React中直接使用Redux

    开始之前需要强调一下,redux和react没有直接的关系,你完全可以在React, Angular, Ember, jQuery, or vanilla JavaScript中使用Redux 。 尽管这样说,redux依然是和React库结合的更好,因为他们是通过state函数来描述界面的状态,Redux可以发射状态的更新, 让他们作出相应; 目前redux在react中使

    2024年01月23日
    浏览(59)
  • 在react中使用redux && react-redux的使用demo

    前言: redux是一种状态管理工具,可以存储和操作一些全局或者很多组件需要使用的公共数据。 平心而论,redux的使用对于新上手来说不太友好,多个依赖包的,多种api的结合使用,相对来说比做同样一件事的vuex用起来比较麻烦.不过,熟能生巧,用多了也就习惯了,下面是个人的一个d

    2024年02月06日
    浏览(55)
  • 【React】React中编写CSS,Redux

    ❤️ Author: 老九 ☕️ 个人博客:老九的CSDN博客 🙏 个人名言:不可控之事 乐观面对 😍 系列专栏: style接受一个采用小驼峰命名属性的JS对象,而不是CSS字符串,可以动态获取当前state中的状态 缺点:1.写法上面需要使用驼峰2.编写样式没有提示3.大量的样式,代码混乱4

    2024年02月09日
    浏览(38)
  • 【React】React中编写CSS,Redux,RTX

    ❤️ Author: 老九 ☕️ 个人博客:老九的CSDN博客 🙏 个人名言:不可控之事 乐观面对 😍 系列专栏: style接受一个采用小驼峰命名属性的JS对象,而不是CSS字符串,可以动态获取当前state中的状态 缺点:1.写法上面需要使用驼峰2.编写样式没有提示3.大量的样式,代码混乱4

    2024年02月08日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包