当前位置 : 主页 > 网络编程 > JavaScript >

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

来源:互联网 收集:自由互联 发布时间:2023-02-08
目录 在组件中监听redux中state状态的改变 解决方式 React和redux的状态处理 在组件中监听redux中state状态的改变 解决方式 1、在组件中引入store 2、在constructor构造器方法中,重写store.subsc
目录
  • 在组件中监听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和自动封装无状态组件为有逻辑的组件,这种情况下我们只要写无状态组件,省了很多工作量。

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持易盾网络。

    网友评论