日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網(wǎng)站首頁 編程語言 正文

redux與react-redux的學習筆記之react-redux

作者:Mr_Debugger 更新時間: 2022-11-14 編程語言

redux與react-redux

  • 前言
  • 一、redux和react-redux是啥?
  • 二、redux使用步驟
    • 1.引入庫
    • 2.原理圖
      • 原理圖釋義
      • actions
        • 1)含義
        • 2)demo
      • store.js
        • 1)含義
        • 2)demo
      • reducer.js
        • 1)含義
        • 2)demo
      • Count.jsx
        • 1)含義
        • 2)demo
      • Person.jsx
  • 三、redux開發(fā)者工具的使用
  • 總結


前言

工作中Vue為主,React使用逐漸生疏,對redux僅達到會用的地步。偶爾遇到React項目,用到redux也就是把別人寫過的東西重寫一遍,最近有時間去B站白嫖了一下 React教程。寫個筆記記錄下!!!


一、redux和react-redux是啥?

redux是 JavaScript 狀態(tài)容器,提供可預測化的狀態(tài)管理,是一個獨立的庫可以搭配UI框架進行使用。
與redux稍加不同的是,react-redux是 React 的官方 Redux UI 綁定庫,可以訂閱 store、檢查更新數(shù)據(jù)和觸發(fā)重新渲染的過程可以變得更加通用和可復用。
簡單的說,react-redux最終還是使用redux去取數(shù)據(jù),不過是封裝一層方便使用redux的api。
相對于Vuex的簡單無腦操作,這兩個算是稍微麻煩一點的。不過后續(xù)阿里封裝了個hox,使用起來感覺簡單了很多。

二、redux使用步驟

1.引入庫

代碼如下(示例):

npm install react-redux

2.原理圖

在這里插入圖片描述

原理圖釋義

1.所有的UI組件都應該包裹一個容器組件,他們是父子關系
2.容器組件是真正和redux打交道的,里面可以隨意的使用redux的api
3.UI組件不能使用任何redux的api
4.容器組件會傳給UI組件:1)redux中所保存的狀態(tài),2)用于操作狀態(tài)的方法
5.備注:容器給UI傳遞:狀態(tài)、操作狀態(tài)的方法,均通過props傳遞

actions

1)含義

Action 是把數(shù)據(jù)從應用傳到 store 的有效載荷。它是 store 數(shù)據(jù)的唯一來源。一般來說你會通過 store.dispatch() 將 action 傳到 store。

action返回的是Object類型的叫做同步action
action返回的是Function類型的叫做異步 action
異步action:
(1).明確:延遲的動作不想交給組件自身,想交給action
(2).何時需要異步action:想要對狀態(tài)進行操作,但是具體的數(shù)據(jù)靠異步任務返回(非必須)
(3).具體編碼:
    1).cnpm i redux-thunk,并配置在store中,//行駛轉換程序
    2).創(chuàng)建action的函數(shù)不再返回一般對象,而是一個函數(shù),該函數(shù)中寫異步任務
    3).異步任務有結果后,分發(fā)一個同步的action去真正的操作數(shù)據(jù)
(4).備注:異步action不是必須要寫的,完全可以自己等待異步任務的結果再去分發(fā)同步action

2)demo

//redux文件夾下新建constant.js文件
/* 該模塊適用于定義action對象中type類型的常量值
目的只有一個:便于管理的同時防止單詞寫錯   
 */

export const INCREMENT = 'increment'

export const DECREMENT = 'decrement'

export const SET_OPERATOR = 'setOperator'
//redux文件夾下新建action文件夾
//action下新建count_actions.js
/*
 該文件專門為Count組件生成求和count_actions對象   
 */

import {INCREMENT, DECREMENT} from '../constant'

export const incrementAction = (data) => ({ type: INCREMENT, data })//同步action
//同步action,就是指action的返回值為Object類型的一般對象
export function decrementAction(data){   
    return {     
        type: DECREMENT, 
        data   
    }//返回的是一個對象,普通數(shù)據(jù)類型,同步action,返回對象為異步
}
//異步action,就是指action的返回值為函數(shù)
//異步action中,一般都會調用同步action,異步action不是必須要用的
export const incrementAsyncAction = (data, time) => {
    return (dispatch)=>{//返回對象為異步action
        setTimeout(()=>{
            dispatch(incrementAction(data))
        }, time)
    }
}
//action下新建user_action.js
import { SET_OPERATOR } from '../constant'

export function setOperator(data){
    return{
        type: SET_OPERATOR,
        data,
    } 
}

store.js

1)含義

store是一個狀態(tài)管理器,是一個倉庫,存儲公共的狀態(tài)數(shù)據(jù)。Redux 應用只有一個單一的 store

1)引入redux中的createStore函數(shù),創(chuàng)建一個store
2)createStore調用時要傳入一個為其服務的reducer
3)記得暴露store對象
4)  redux只負責管理狀態(tài),至于狀態(tài)的改變驅動著頁面的展示要靠我們自己寫

2)demo

//redux文件夾新建store.js
//引入creacteStore,專門用于創(chuàng)建redux中最核心的store對象,applyMiddleware執(zhí)行中間件
import { legacy_createStore as createStore, applyMiddleware} from "redux";
//引入redux-thunk用于支持異步action
import thunk from 'redux-thunk'
//引入為組件服務的reducer
import rootReducers   from './reducers'
const store  = createStore(rootReducers, applyMiddleware(thunk))
//暴露出去
export default store

reducer.js

1)含義

Reducers 指定了應用狀態(tài)的變化如何響應 actions 并發(fā)送到 store 的,記住 actions 只是描述了有事情發(fā)生了這一事實,并沒有描述應用如何更新 state。

1)reducer的本質是一個函數(shù),接收:preState,action,發(fā)布加工后的狀態(tài)
2)reducer有兩個作用:初始狀態(tài),加工狀態(tài)
3)reducer被第一次調用時,是store自動觸發(fā)的,傳遞的preState是undefined

2)demo

//redux文件夾下新建reducers文件夾
//新建count_reducer.js
import {INCREMENT, DECREMENT} from '../constant'
//監(jiān)測提交過來的action,preState是前一條數(shù)據(jù),初始化時默認為0
const counter = (preState = 0,action)=>{
    const {type, data}= action
    switch(type){
        case INCREMENT:
            return preState + data;
        case DECREMENT:
            return preState - data;
        default:
            return preState;
    }
}

export default counter;
//redux文件夾下新建reducers文件夾
//新建user_reducer.js
import { SET_OPERATOR } from '../constant'

const operator = (preState = {}, action)=>{
    const {type, data}= action
    switch(type){
        case SET_OPERATOR:
            return Object.assign(preState, data);
        default :
            return preState
    }
}

export default operator;
//redux文件夾下新建reducers文件夾
//新建index.js

import { combineReducers } from 'redux';
import counter from './count_reducer';
import operator from './user_reducer'

// 合并多個 reduce
const rootReducers = combineReducers({
    counter:counter,
    operator:operator
});

export default rootReducers;

Count.jsx

1)含義

操作組件,里面包含數(shù)據(jù)加減,和數(shù)據(jù)賦值兩個功能

2)demo

//引入Count的UI組件
// import CountUI from '../../components/Count'
//引入action  
import { 
    incrementAction, 
    decrementAction, 
    incrementAsyncAction 
} from '../../redux/actions/count_actions'
//引入connect用于連接UI組件與redux
import { connect } from 'react-redux'
// import store from '../../redux/store'
import React, { Component } from 'react'
import store from '../../redux/store'

import { setOperatorAction } from '../../redux/actions/user_action'

class Count extends Component {
    state = {
        
    }
    
    //加
    increment=()=>{
        const {value}=this.selectNumber
        this.props.increment(value*1)
    }
    //減
    decrement=()=>{
        const { value } = this.selectNumber
        this.props.decrement(value*1)
    }
    //當前求和的數(shù)據(jù)為奇數(shù)再加
    incrementIfOdd=()=>{
        const counter = this.props.count.counter
        const { value } = this.selectNumber
        if(counter % 2 !=0) {
            this.props.increment(value*1)
        }
        
    }
    //異步加
    incrementAsync=()=>{
        const { value } = this.selectNumber
        this.props.incrementAsync(value*1, 1000)
    }
    addUserInfo = () => {
        const operator = {
            name: '大黃'+Math.floor(Math.random()*100),
            age: Math.floor(Math.random()*100)
        }
        this.props.setOperator(operator)
    }   
    render() {
        console.log(this.props)
        return (
            <div> 
                <h2>Person數(shù)組的長度{this.props.personLen.length}</h2>
                <h1>當前求和為{this.props.count}</h1>
                <select ref={c=>this.selectNumber =c}>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>
                <button onClick={()=>{this.increment()}}>+</button>
                <button onClick={()=>{this.decrement()}}>-</button>
                <button onClick={()=>{this.incrementIfOdd()}}>如果為奇數(shù)</button>
                <button onClick={()=>{this.incrementAsync ()}}>異步增加 </button>
            </div>
        )
    }
}
//a函數(shù)的返回對象的key就作為傳遞給UI組件props的key,value就作為傳遞給UI組props的value---狀態(tài)
const mapStateToProps = (state)=> ({count: state.counter, personLen: state.operator})
//b函數(shù)的返回對象的key就作為傳遞給UI組件props的key,value就作為傳遞給UI組props的value---操作狀態(tài)的方法
//一般寫法 
// const mapDispatchToProps = (dispatch)=> ({
//     increment: (number)=> dispatch(incrementAction(number)),
//     decrement: (number)=> dispatch(decrementAction(number)),
//     incrementAsync: (number)=> dispatch(incrementAsyncAction(number, 2000)),
// })
//高級寫法
//因為用了react-redux能夠自動dispatch
const mapDispatchToProps = {
    increment: incrementAction,
    decrement: decrementAction,
    incrementAsync: incrementAsyncAction,
    setOperator: setOperatorAction
}
//創(chuàng)建一個容器組件
const CountContainer = connect(mapStateToProps, mapDispatchToProps)(Count)
//暴露容器組件
export default CountContainer;

//export default connect()(CountUI)
  
//App.js
import Count from './container/Count'
import Person from './container/Person'
// import store from './redux/store'
function App() {
  return (
    <div className="App">
      <Count/>
      <hr/>
      <Person/>
    </div>
  );
}

export default App;


1)明確兩個概念:
    1UI組件:不能使用redux的api,只負責頁面的呈現(xiàn)和交互等
    2)容器組件:負責和redux通信,將結果交給UI組件
2)如何創(chuàng)建一個容器組件---react-redux的connect函數(shù)
    connect(mapStateToProps, mapDispatchToProps)(UI組件)
    -mapStateToProps:映射狀態(tài),返回值是一個對象
    -mapDispatchToProps:映射操作狀態(tài)的方法,返回值是一個對象
3)備注:容器組件中的store是靠props穿進去的,而不是在容器組件中直接引入

Person.jsx

//引入Count的UI組件
// import CountUI from '../../components/Count'
//引入action  
//引入connect用于連接UI組件與redux
import { connect } from 'react-redux'
// import store from '../../redux/store'
import React, { Component } from 'react'
import { setOperatorAction } from '../../redux/actions/user_action'

class Count extends Component {
    state = {
        
    }
    addUserInfo = () => {
        const name = this.nameNode.value
        const age = this.ageNode.value
        const personObj = {id: Math.floor(Math.random()*100), name, age}
        this.props.setOperator(personObj)
        this.nameNode.value = ''
        this.ageNode.value = ''
        console.log(name, age)
    }   
    render() {
        console.log(this.props.operator, this.props.count)
        return (
            <div> 
                <h2>Person組件,Count組件的總和為{this.props.count}</h2>
                <div>
                    <input ref={c=> this.nameNode= c} type="text" placeholder="輸入名字"/>
                    <input ref={c=> this.ageNode= c} type="text"  placeholder="輸入年齡"/>
                    <button onClick={()=>{this.addUserInfo()}}>添加用戶信息</button>
                    <ul>
                        {
                            this.props.operator.map(item=>{
                                return <li key={item.id}>{item.name}---{item.age}</li>
                            })
                        }
                    </ul>
                </div>
            </div>
        )
    }
}
//a函數(shù)的返回對象的key就作為傳遞給UI組件props的key,value就作為傳遞給UI組props的value---狀態(tài)
const mapStateToProps = (state)=> ({operator: state.operator, count: state.counter})
//高級寫法
//因為用了react-redux能夠自動dispatch
const mapDispatchToProps = {
    setOperator: setOperatorAction
}
//創(chuàng)建一個容器組件
const CountContainer = connect(mapStateToProps, mapDispatchToProps)(Count)
//暴露容器組件
export default CountContainer;

//export default connect()(CountUI)
  
1)定義一個Person組件,和Count組件通過redux共享數(shù)據(jù)
2)為Person組件編寫,reducer、action,配置constant常量
3)重點:Person的reducer和Count的Reducer要使用combineReducer進行合并,合并后的總狀態(tài)是一個對象
4)交給store的是總reducer,最后注意在組件中取出狀態(tài)的時候,記得取到位
//index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import store from './redux/store'
import App from './App';
import {Provider} from 'react-redux'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
   /*給容器組件傳遞store */
  <Provider store={store}>
    <App />
  </Provider>
);  
// 監(jiān)聽redux中狀態(tài)的變化,如果redux的狀態(tài)發(fā)生了變化,
//那么重新渲染App組件
//react-redux不用再監(jiān)測了
// store.subscribe(() => {
//   root.render(
//     <Provider store={store}>
//       <App />
//     </Provider>
//   );  
// })

三、redux開發(fā)者工具的使用

npm i redux-devtools-extension
store文件
//引入redux-devtools-extension
import { composeWithDevTools } from 'redux-devtools-extension'

// const store  = createStore(rootReducers, composeWithDevTools())
const store  = createStore(rootReducers, composeWithDevTools(applyMiddleware(thunk)))

總結

1)容器組件和UI組件整合成一個文件
2)無需自己給容器組件傳遞store,給<App/>包裹 <Provider store={store}>即可
3)使用了react-redux無需自己檢測redux中狀態(tài)的變化,容器組件可以自動完成這個工作
4)mapDispatchToProps也可以簡寫成一個對象
5)一個組件要和redux打交道要經(jīng)過幾步?
    1)定義好UI組件---不暴露
    2)引入connect生成一個容器組件,并暴露,寫法如下:
        connect(state=>(
            {key:value},//映射狀態(tài)
        ),
        {
            key:action//映射操作狀態(tài)的方法
        })UI組件中通過this.props.***讀取和操作狀態(tài)

原文鏈接:https://blog.csdn.net/chenacxz/article/details/127837231

欄目分類
最近更新