網站首頁 編程語言 正文
在組件中監聽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和自動封裝無狀態組件為有邏輯的組件,這種情況下我們只要寫無狀態組件,省了很多工作量。
原文鏈接:https://blog.csdn.net/qq_36742720/article/details/86226428
相關推薦
- 2022-10-16 C#自定義畫刷原理解析_C#教程
- 2022-11-04 Linux下自動刪除過期備份和自動異地備份的腳本_linux shell
- 2022-03-12 .NET?MemoryCache如何清除全部緩存_C#教程
- 2022-07-15 Python計算圖片數據集的均值方差示例詳解_python
- 2022-08-02 python?GUI編程實現掃雷游戲_python
- 2022-06-25 python格式化輸出實例(居中、靠右及靠左對齊)_python
- 2022-06-16 C#使用符號表實現查找算法_C#教程
- 2022-12-22 React?Hook?-?自定義Hook的基本使用和案例講解_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支