React在组件中如何监听redux中state状态的改变

目录
  • 在组件中监听redux中state状态的改变
    • 解决方式
  • React和redux的状态处理

在组件中监听redux中state状态的改变

解决方式

1、在组件中引入store

2、在constructor构造器方法中,重写store.subscribe方法(该方法即是监听state状态改变的放过)

组件完整代码如下:

import React, { Component } from 'react'
import CSSModules from 'react-css-modules' 
import { connect } from 'react-redux'
import store from '../../redux/store' 
import styles from './BgMusic.css'
 
@CSSModules(styles)
class BgMusic extends Component {
  // 构造器
  constructor(props) {
    super(props)
    console.log('执行了constructor')
    // 监听state状态改变
    store.subscribe(() => {
      console.log('state状态改变了,新状态如下')
      console.log(store.getState())
      const state = store.getState()
      if (state.music.play) {
        // 播放背景音乐
        this.audio1.play()
      }
      else {
        // 暂停背景音乐
        this.audio1.pause()
      }
    })
  }
  render() {
    return (
      <div className={styles.container}>
        <audio ref={audio1 => { this.audio1 = audio1 }} className={styles.hidden} autoPlay="autoplay" controls="controls" loop="loop" preload="auto" src="./music/music.mp3">
            你的浏览器版本太低,不支持audio标签
        </audio>
      </div>
    )
  }
}
export default connect(
  // 这里的state,就是公共容器中的state,而不是当前组件的state。在这里定义了之后,在当前组件中,就可以通过this.props.music拿到该对象
  state => ({ music: state.music }),
)(BgMusic)

React和redux的状态处理

我们知道react中state是组件更新的唯一指标,并且只能通过组件的this.setState方法触发组件的重新渲染。这种形式导致了一个组件A想要触发另一个组件B更新,就必须触发组件B内部的this.setState。一般是通过一开始就在B中设置委托到组件A中。

例如:

class B extends React.Component{
    state={key:"value"}
    handle(){
        this.setState({key:"newvalue"})
    }
    render(){
        return <div>
                <A onOk=>{this.handle.bind(this)}/>
                <span>{this.state.key}</span>
            </div>
    }
}
class A extends React.Component{
    render(){return <button onClick={this.props.onOk}>click</button>}
}

这样也就隐形的要求B组件必须是A组件的父组件,换句话说:如果一个组件想要触发另一个组件的更新,需要触发者是被触发者的子组件。 父组件可以将更新的函数预先定好,作为属性传入子组件中,这样子组件中调用这个属性函数就触发了父组件的更新,本质是父组件将自己的一个函数委托给子组件处理。

当组件变得又多又复杂的时候,可能需要跨越好多层父子关系来传递这个闭包,这使得状态的管理非常复杂。

例如这种情况下,C想要触发A.setState,那就需要A先封好闭包作为属性传给B,B再传给C,C在合适的时机调用。调用完了,A的setState会引起所有的子组件重新render。

如果C想要触发D的更新,则也需要A作为中介,将D中要更新的部分拿出来,作为props由A来传入,这样还是按照之前的做法,C可以引起A的render,进而导致了所有组件render,也就包括了D。不过其实我们只想要D更新,其他组件并不需要更新。而且我们看到state的存储很乱,有时候我们将state存到本组件中,由自己掌握更新的时机,有时候需要交给父组件来掌握,此时子组件是无状态的,所有数据由父组件通过props传入。

这种方式无论从闭包传递还是过多的组件render上都是不好的,我们思考能不能通过更高效的方式完成这件事。首先是闭包传递,其实本质上是A把更新这件事放到一个函数中,然后把该函数作为属性传递给了子组件。我们可以这样来做,在A中设置一个事件监听器当事件触发的时候就更新状态,而在C中设置一个事件激发当合适的时机(如点击按钮)触发这个事件,这样就完成了直接触发另一个组件的更新。这样每个组件都有自己的state,并且都监听一个自己特定的事件,如果事件触发,就相应的调用setState完成自己的更新。

Redux就是这种思路,核心概念是store,所有组件ABCDE的state都存到了store.state中,这个变量只能通过触发action才能改变,并且专门定义了这种根据action更新store.state值的函数叫reducer。当然了改变了这个变量的值对我们整个react应用没有任何影响,还需要把这个值和每个组件内的state关联起来。每个组件中都有一个store.subcribe(func),即每个组件都可以监听这个store.state的变化,如果变化就触发这个函数,然后可以看变量中是不是和自己相关的例如可以在store中这样存储{a:xxx,b:xx,c:xx,d:xx}这样A只需要检查store.getState().a是不是有变。

如下:

上图中,其实ABCD的回调函数都会触发,只不过触发后有个判断,只有D的发生了变化,所以只有D进行后续setState和render操作。

Redux的思想是这样的,首先state全都交到store中来保存,每个组件订阅store的变化,一但发生变化,就把自己的state同步。store的变化由action这种方式唯一触发,管理起来也方便。不过Subscribe写起来太麻烦了,所以ReactRedux模块提供了Provider 和connect,可以很方便的完成自动Subscribe和自动封装无状态组件为有逻辑的组件,这种情况下我们只要写无状态组件,省了很多工作量。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • React-router4路由监听的实现

    React-router 4 React Router4是一个纯React重写的包,现在的版本中已不需要路由配置,一切皆组件. 问题出发点 最近在一个新的H5项目中使用了react router 4 ("react-router-dom": "^4.2.2"),项目中的一部分页面是需要给app客户端的同学使用,这样H5项目中的title就不能一成不变,需要显示对应页面的title,所以,我们就需要去监听路由变动来更改title. 思路 在react中,例如:在父路由

  • react实现数据监听方式

    目录 react 数据监听 react事件监听三种写法 方式一 方式二 方式三 react 数据监听 监听组件传递的值:  componentWillReceiveProps(newProps)  {      参数为给组件传递的参数  } 监听组件内部状态的变化: componentDidUpdate(prevProps,prevState){     参数分别为改变之前的数据状态对象     if(prevState.属性名!=this.state.属性名)     {         ..

  • React和Vue中监听变量变化的方法

    React 中 本地调试React代码的方法 yarn build 场景 假设有这样一个场景,父组件传递子组件一个A参数,子组件需要监听A参数的变化转换为state. 16之前 在React以前我们可以使用 componentWillReveiveProps 来监听 props 的变换 16之后 在最新版本的React中可以使用新出的 getDerivedStateFromProps 进行props的监听, getDerivedStateFromProps 可以返回 null 或者一个对象,如果

  • React事件监听和State状态修改方式

    目录 React事件监听和State状态修改 React事件监听相关例子 React事件监听和State状态修改 on*函数可直接使用,但只能使用在html标签上,自己创建的组件标签不可 组件可以增加state状态,修改用setState方法,修改会有缓存,只能保证在渲染到页面之前会改好.所以setState后立马去使用值可能是不对的 狗子组件1:点击会打印bark和run class Dog extends Component {   bark () {     console.log('ba

  • 前端项目中的Vue、React错误监听

    目录 一. Vue 错误监听 window.onerror errorCaptured 生命周期 errorHandler 异步错误 答案 扩展 二.React 错误监听 ErrorBoundary dev 和 build 事件报错 异步错误 答案 扩展 一. Vue 错误监听 题目: 如何统一监听 Vue 组件报错? 分析: 真实项目需要闭环,即考虑各个方面,除了基本的功能外,还要考虑性能优化.报错.统计等. 而个人项目.课程项目一般以实现功能为主,不会考虑这么全面.所以,没有实际工作经验的同

  • React在组件中如何监听redux中state状态的改变

    目录 在组件中监听redux中state状态的改变 解决方式 React和redux的状态处理 在组件中监听redux中state状态的改变 解决方式 1.在组件中引入store 2.在constructor构造器方法中,重写store.subscribe方法(该方法即是监听state状态改变的放过) 组件完整代码如下: import React, { Component } from 'react' import CSSModules from 'react-css-modules'  imp

  • vue中watch监听对象中某个属性的方法

    目录 immediate 和 handler deep 深度监听 以currentParams为例,监听selOrgId属性 immediate 和 handler watch 的用法有个特点,就是当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行.如果我们需要在最初绑定值得时候也执行函数,就需要用到 immediate 属性. 'currentParams.selOrgId': { handler(newV, oldV) { console.log("watch", ne

  • 解决Vue.js父组件$on无法监听子组件$emit触发事件的问题

    最近学习vuejs看例子中用$on无法监听子组件$emit触发事件: 使用版本 vue.js 2.2.5 参考文献 1.vuejs API 2.解决实例 问题分析 1.之前写的自定义组件事件触发为this.$emit("myclick",this.todo.text);,这样this指的是todo-item的每一项,而最后vm.$on监听的是app组件,也就出说监听的是父节点,而触发的是子节点,故监听不到这个事件的. 解决思路 1.将触发事件放在父节点上触发,就可以监听到触发的事件了,

  • vue组件props属性监听不到值变化问题

    目录 props属性监听不到值变化问题 props监听变化的几种方式 应用场景 1.computed 计算属性 2.methods 方法 3.watch 侦听器 props属性监听不到值变化问题 在写项目时遇到一个问题,父组件传到子组件的prop,在子组件监听不到变化, 遂查看vue文档,得知watch有一种深度监听的方法. 阅读vue文档如下代码.=> var vm = new Vue({   data: {     a: 1,     b: 2,     c: 3,     d: 4,  

  • vue监听页面中的某个div的滚动事件并判断滚动的位置

    在开发中常常会遇到这样一个vue页面,页面分为左右两部分,左边是目录树,右边是一个类名为xq-box的div,在xq-box中多个div上下并列布局,每个div中的内容就对应着左边目录树中的相应节点,现在的目标是,要监听这个xq-box滚动事件,右边一旦开始滚动,就要知道滚动到哪个子div,并让左边的目录树中对应的节点高亮显示.要怎么做呢? 1.首先,先写好大概的页面布局,这里要注意,右边xq-box的子div要绑定"'xqItem'+序号"的id,为了下面用js能获取到匹配的dom元

  • vue3如何使用watch监听props中的数据

    目录 情况一:监听 props 中基本数据类型 情况二:监听 props 中引用数据类型且父组件不改变地址指向 情况三:监听 props 中引用数据类型且父组件改变地址指向 总结 写在最后 情况一:监听 props 中基本数据类型 父组件中对传入数据的处理 const handleClick = () => { testStr.value += 'P' } 子组件中监听传入的数据 watch( () => props.testStr, (newVal, oldVal) => { cons

  • Vue3中watch监听对象的属性值(监听源必须是一个getter函数)

    目录 Vue3 中使用 watch 侦听对象中的具体属性 1.前言 2. 原因 3.watch源码分析 4.doWatch源码分析 5.总结 Vue3 中使用 watch 侦听对象中的具体属性 1.前言 <script lang="ts" setup> // 接受父组件传递的数据 const props = defineProps({ test: { type: String, default: '' } }) // 使用 watch 侦听 props 中的 test 属性

  • AngularJS中watch监听用法分析

    本文实例讲述了AngularJS中watch监听用法.分享给大家供大家参考,具体如下: ANGULAR 监听使用: 当angular数据模型发生变化时,我们需要如果需要根据他的变化触发其他的事件. $watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你. $watch(watchExpression, listener, objectEquality); watchExpression 需要监控的表达式 listener 处理函数,函数参数如下  function

  • iOS开发中Swift3 监听UITextView文字改变的方法(三种方法)

    在项目中使用文本输入框出UITextField之外还会经常使用 UITextView ,难免会有需求监听UITextView文本框内文本数量.下面介绍在swift3中两种常用方式 方式一: 全局通知 1.注册通知 在合适位置注册监听UITextView文本变化的全局通知 //UITextView 监听开始输入的两种方法 //方法一:通知 NotificationCenter.default.addObserver(self, selector: #selector(ComposeVC.textV

  • 详解ASP.NET Core中配置监听URLs的五种方式

    默认情况下,ASP. NET Core应用会监听一下2个Url: http://localhost:5000 https://localhost:5001 在本篇博文中,我将展示如何使用五种不同的方式改变应用监听的URLs. 在ASP.NET Core项目启动时,有多种配置监听Url的方式,在我之前的一篇博客中,已经展示了在ASP.NET Core 1.0中如何应用不同的方式配置,在ASP.NET Core 3.x中,大部分方式还是一样的. UseUrls() - 在Program.cs配置程序

随机推荐