最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React各種狀態(tài)管理器的解讀及使用方法

 更新時(shí)間:2021年12月11日 15:11:31   作者:印第安老劉頭  
這篇文章主要介紹了對(duì)于React各種狀態(tài)管理器的解讀,文中給大家提到了狀態(tài)管理器是如何使用的,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

首先我們要先知道什么是狀態(tài)管理器,這玩意是干啥的?

當(dāng)我們?cè)诙鄠€(gè)頁(yè)面中使用到了相同的屬性時(shí)就可以用到狀態(tài)管理器,將這些狀態(tài)存到外部的一個(gè)單獨(dú)的文件中,不管在什么時(shí)候想使用都可以很方便的獲取。

react和vue有些不同,react沒(méi)有自己專屬的狀態(tài)管理方式。它使用的其實(shí)是js相關(guān)的狀態(tài)管理器。我們需要記住的是,視圖可以引起狀態(tài)的改變,而狀態(tài)的改變會(huì)導(dǎo)致視圖的二次渲染。

說(shuō)了這么半天,那么我們?cè)趓eact中到底是怎樣使用狀態(tài)管理器的呢?

redux閃亮登場(chǎng)

redux的前身技術(shù)是flux,他和flux很相像,但是又不完全相同。兩者都規(guī)定將模型的更新邏輯全部集中在一個(gè)層面中(Flux之中的store,redux之中的reducer);但是redux中沒(méi)有dispatcher的概念,他依賴的是純函數(shù)來(lái)做事件處理器;并且redux不回去修改你的數(shù)據(jù),它會(huì)返回一個(gè)新的對(duì)象用于更新state狀態(tài)。

首先我們先來(lái)認(rèn)識(shí)一下redux中的一些屬性

1、store:

保存數(shù)據(jù)/狀態(tài)的地方,可以把它看成是一個(gè)容器。記得在整個(gè)應(yīng)用之中只能有一個(gè)store

import { createStore } from 'redux'
const store = createStore(fn)

  2、state:

可以把state看成是store的實(shí)例對(duì)象,他包含了狀態(tài)管理器中所有的狀態(tài),是某個(gè)時(shí)間點(diǎn)所有數(shù)據(jù)/狀態(tài)的集合

const state = store.getState()

  3、action

redux中最重要的屬性之一,唯一修改store種狀態(tài)的方式就是提交一個(gè)action;action是一個(gè)對(duì)象,具有type屬性,通常這個(gè)type屬性作為提交的關(guān)鍵key值

const action = {
    type: 'ADD_TODO',
    payload: 'Learc Redux'  //這里的payload是作為參數(shù)傳入的,可以不寫
}

  4、store.dispatch():

提交action的唯一方式,我們就是通過(guò)這種方式將action提交到狀態(tài)管理器,不管后期使用了什么其他的狀態(tài)管理其工具,最終都?xì)w結(jié)與這里。

store.dispatch({
    type: 'ADD_TODO'
})

 5、reducer:

store在收到action之后,必須返回一個(gè)新的state,這樣view才會(huì)發(fā)生變化,而這個(gè)state的計(jì)算過(guò)程就叫做reducer

reducer是一個(gè)函數(shù),他接受當(dāng)前的state和action,返回一個(gè)全新的state

const reducer = (state = {
  count: 10 //給state中的屬性設(shè)置初始值,因?yàn)闋顟B(tài)管理器在每次刷新后都會(huì)清空,我們可以從本地獲取上次存儲(chǔ)的值作為初始值
}, action) => {
  switch (action.type) {
    case 'REDUCE':
          //    這里可以看到我們根據(jù)action的type值作為key值進(jìn)行查找,當(dāng)dispatch的時(shí)候,就可以根據(jù)這些key值的判斷查找到要執(zhí)行的操作
      return { ...state, count: state.count - action.payload }
          //我們根據(jù)action的需要,在原有的state基礎(chǔ)上,返回了一個(gè)新的state對(duì)象,沒(méi)有修改原來(lái)的state
    case 'ADD':
      return { ...state, count: state.count + action.payload }
   
    default:
      return state;
  }
}
 
export default reducer

可以看到我們返回新的state對(duì)象的方式是通過(guò)ES6中的 ... 語(yǔ)法,這種方式看起來(lái)是不是有點(diǎn)復(fù)雜,有點(diǎn)點(diǎn)low?那么我們介紹一種新的方式,首先引入immutable組件

  這種方式其實(shí)是js實(shí)現(xiàn)了一種深拷貝,將原來(lái)的state對(duì)象深拷貝了一份,這樣對(duì)新的state對(duì)象做出任何修改都不會(huì)影響到原來(lái)的state,是不是特別香!??!

yarn add immutable -S

使用方式:

import { Map } from 'immutable'        //引入Map函數(shù)

const user = (state = Map({        //使用Map深拷貝了state
  isLogin: localStorage.getItem('isLogin') === 'true',    
  token: localStorage.getItem('token') || '',
  adminname: localStorage.getItem('adminname') || '',
  role: localStorage.getItem('role') * 1 || 1
}), action) => {
  switch (action.type) {
    case 'CHANGE_LOGIN_STATE':
      return state.set('isLogin', action.payload)    //set方式寫入
    case 'CHANGE_TOKEN':
      return state.set('token', action.payload)
    case 'CHANGE_ADMIN_NAME':
      return state.set('adminname', action.payload)
    case 'CHANGE_ROLE':
      return state.set('role', action.payload)
    default:
      return state
  }
}

export default user
state => {
    return {
        adminname: state.getIn(['user', 'adminname']),    // get方式獲取值, 參數(shù)是這種形式
            //第一個(gè)參數(shù)的含義: user狀態(tài)管理器中的
            //第二個(gè)參數(shù)含義: 名為adminname的狀態(tài)/屬性
    }
}

6、設(shè)計(jì)狀態(tài)管理器

首先根據(jù)模塊化開(kāi)發(fā)的思想,我們可以在一個(gè)項(xiàng)目中設(shè)計(jì)多個(gè)種類狀態(tài)管理器,最后合并到一個(gè)里面;例如,商品的狀態(tài),用戶信息的狀態(tài)....

import { createStore, combineReducers } from "redux";
// 這個(gè)combineReducers方法就是模塊化開(kāi)發(fā)的關(guān)鍵,它幫助我們把所有分模塊的狀態(tài)管理器合并到一起
import pro from './modules/pro'
import app from './modules/app'
 
const reducer = combineReducers({   //把分模塊創(chuàng)建的所有reducer都集中到這里的reducer
  pro, app
})
 
const store = createStore(reducer)
 
export default store

幫助解讀階段

我們要知道一件事,當(dāng)我們?cè)谀骋粋€(gè)時(shí)間點(diǎn)希望獲取狀態(tài)或者修改狀態(tài)的時(shí)候,狀態(tài)管理器store會(huì)為我們生成一個(gè)state實(shí)例對(duì)象,我們可以對(duì)這個(gè)實(shí)例對(duì)象進(jìn)行操作。state的變化會(huì)引起View視圖的改變,但是因?yàn)橛脩魝兘佑|不到state,只能接觸到View,所以state的變化必然也必須是由View引起的?。?!而action其實(shí)就是view 發(fā)出的一個(gè)通知,當(dāng)用戶修改了view的時(shí)候,就會(huì)發(fā)出這個(gè)通知,告訴程序,state需要發(fā)生改變了。

//我們可以這樣理解,dispatch,action,store三者的關(guān)系可以看成是郵局,郵件,收信人
//我們想寄一封信(action),告訴朋友(收信人),我們找到工作了,需要通過(guò)郵局(dispatch)的幫助;當(dāng)郵局幫我們把郵件送到了收件人的地方時(shí),收件人就獲取到了我要傳遞的信息,也會(huì)做出響應(yīng)的改變
//我們?cè)谡{(diào)用dispatch的時(shí)候,通過(guò)type(key值)找到對(duì)應(yīng)的郵件送到store

狀態(tài)管理器是如何使用的呢?

// 可以通過(guò)provider和connect在組件中對(duì)狀態(tài)管理器進(jìn)行‘鏈接',鏈接成功之后就可以使用狀態(tài)管理器中的狀態(tài)和方法了
 
// /src/xxx/index.jsx
import {connect} from 'react-redux'
 
function App (props) {
    ...
}
export default connet(mapStateToProps, mapDispatchToProps)(App)
     
// /index.js
import {Provider} from 'react-redux'
import App from './App.jsx'
import store './store/index.js'
     
ReactDom.render (
    <React.StrictMode>
        <Provider store = { store }>
            <App />
        </Provider>
    </React.StrickMode>
)
 
//也可以使用到裝飾器的高階函數(shù) @connect @withRouter
 
//以往從狀態(tài)樹(shù)取出對(duì)應(yīng)的數(shù)據(jù),讓后通過(guò)props傳給組件使用通過(guò)react-redux自帶的connect()方法
class Home extends React.Component {
    //....
}
export default connect(state => ({todos: state.todos}))(Home);
 
//使用裝飾器的話就變成這樣,好像沒(méi)那么復(fù)雜
@connect(state => ({ todos: state.todos }))
class Home extends React.Component {
    //....
}

  這里我們對(duì)這種方式做出講解:

我們要鏈接狀態(tài)管理器,首先在整個(gè)項(xiàng)目的入口文件index.js中引入狀態(tài)store,通過(guò)Provider的方式將store作為參數(shù)傳遞給子組件,有點(diǎn)類似于祖先組件給后代組件傳值的方式

其次,我們要在使用狀態(tài)管理器的組件中通過(guò)connect這一個(gè)高階函數(shù)進(jìn)行連接,該高階函數(shù)的原理是,傳入函數(shù)作為參數(shù),返回另一個(gè)函數(shù)

mapStateToProps:

從名字可以看出,是把state中的狀態(tài)遍歷處理,放到props中,我們就可以在函數(shù)式組件中的props參數(shù)值里面獲取到state.

mapDispatchToProps:

將狀態(tài)管理器中的提交方法存入到props中,這樣我們就可以在組件中對(duì)狀態(tài)管理器中的狀態(tài)進(jìn)行修改。

const App = (props) => {
    // 組件中直接就可以通過(guò)props訪問(wèn)到狀態(tài)管理器中的狀態(tài)
    props.adminname
    props.count
    props.bannerList
    props.reduceFn
    ...
}
export default connect(
    // 可以看到這里就是傳入兩個(gè)函數(shù),返回兩個(gè)函數(shù)
    state => {
        return {
            adminname: state.getIn(['user', 'adminname']),  //這是一種存儲(chǔ)狀態(tài)的方式,一會(huì)會(huì)講到
            count: state.app.count,     //參數(shù)是state,我們把a(bǔ)pp狀態(tài)管理器中的count屬性傳遞到props中的count
            bannerList: state.pro.bannerList,
        }
    },
    dispatch => {
        return {
            reduceFn () {   //我們?cè)谶@里定義了一個(gè)reduceFn,里面是dispatch的方法,我們?cè)趐rops中就可以通過(guò)reduceFn這個(gè)方法發(fā)送'REDUCE'提交的信息
                dispatch({
                    type: 'REDUCE',
                    payload: 5  //payload為參數(shù),可以不傳
                })
            }
        }
    }
)(App)

  我們除了可以使用這種基本的方式修改狀態(tài)意外,還可以使用一些工具

redux-thunk、redux-saga

redux-thunk的使用

//在store.js之中把thunk引入并掛載到狀態(tài)管理器中
 
import { createStore, combineReducers, applyMiddleware} from 'redux'
 
import thunk from 'redux-thunk'
import app from './modules/app'
import pro from './modules/pro'
 
const reducer = combineReducers({
  app, pro
})
// 通過(guò)applyMiddleware將thunk掛載到狀態(tài)管理器
const store = createStore(reducer, applyMiddleware(thunk))
 
export default store

  然后我們單獨(dú)設(shè)計(jì)一個(gè)文件用來(lái)封裝修改狀態(tài)的方式,包含異步方式

// .../store/actionCreator/pro.js
 
// 這個(gè)文件就是專門用來(lái)觸發(fā)異步操作
// thunk模塊執(zhí)行的時(shí)候, actionCreator 函數(shù)有默認(rèn)的參數(shù)為dispatch
// 該dispatch 可以用來(lái)觸發(fā)reducer
// 有時(shí)候在觸發(fā)異步的時(shí)候, 需要傳遞參數(shù),這個(gè)時(shí)候,可以在函數(shù)內(nèi)部返回一個(gè) actionCreator 函數(shù)
const actions = {
  getBannerListAction (dispatch) {
    fetch('http://121.89.205.189/api/banner/list')
    .then(res => res.json())
    .then(res => {
      dispatch({
        type: 'CHANGE_BANNER_LIST',
        payload: res.data
      })
    })
  },
  getProListAction (count) {   //有參數(shù),返回一個(gè)函數(shù),函數(shù)參數(shù)默認(rèn)為dispatch
    count = count || 1
    return function (dispatch) {
      fetch('http://121.89.205.189/api/pro/list?count=' + count)
      .then(res => res.json())
      .then(res => {
        dispatch({
          type: 'CHANGE_PRO_LIST',
          payload: res.data
        })
      })
    }
  }
}
 
export default actions

  可以把上面的步驟看成定義了一個(gè)action的對(duì)象,里面有一些提交action的dispatch,當(dāng)我們要在組件中要修改狀態(tài)時(shí),可以直接在這個(gè)對(duì)象中使用函數(shù),函數(shù)會(huì)自動(dòng)發(fā)起請(qǐng)求,提交action。

在下面組件中的使用也可以看出來(lái),我們dispatch(actions.getBannerListAction);其實(shí)就是提交aciton的形式,只不過(guò)我們把a(bǔ)ction修改和異步請(qǐng)求封裝起來(lái)了

import actions from './store/actionCreator/pro'
const App = (props) => {
    // props之中可以直接訪問(wèn)到
    props.reduceFn()
    props.addFn()
    props.getBannerList()
    props.getProList()
}
 
const mapStateToProps = (state) => {
  return {
    count: state.app.count,
    bannerList: state.pro.bannerList,
    proList: state.pro.proList
  }
}
 
const mapDispatchToProps = (dispatch) => {
  return {
    reduceFn () {       //通過(guò)正常方式修改狀態(tài)
      dispatch({       
        type: 'REDUCE',
        payload: 5
      })
    },
    addFn () {
      dispatch({
        type: 'ADD',
        payload: 5
      })
    },
    getBannerList () {      //通過(guò)thunk方式修改狀態(tài)
      dispatch(actions.getBannerListAction)
    },
    getProList () {
      dispatch(actions.getProListAction(2))
    }
  }
}
 
export default connect(mapStateToProps, mapDispatchToProps)(App)

  鏈接的方式和普通的react-redux一模一樣,最后也是通過(guò)dispatch一個(gè)action的方式修改狀態(tài)

react-saga的使用

安裝redux-saga

yarn add redux-saga  immutable redux-immutable -S

  可以把redux-saga和redux-thunk看作是一種發(fā)送dispatch的方式,在舊時(shí)代我們送信(dispatch)是通過(guò)汽車、步行;使用工具可以看成是通過(guò)動(dòng)車,飛機(jī)發(fā)送信件

import { createStore, combineReducers, applyMiddleware } from 'redux'
 
import createSagaMiddleware from 'redux-saga'
 
import mySaga from './mySaga' //異步操作說(shuō)明
 
import home from './modules/home'
import app from './modules/app'
 
const reducer = combineReducers({
  app,
  home
})
 
const sagaMiddleware = createSagaMiddleware()   //生成saga中間件
 
const store = createStore(reducer, applyMiddleware(sagaMiddleware))
//建立鏈接
//和thunk一樣,把saga中間件掛載到狀態(tài)管理器中就可以使用saga的方式修改狀態(tài)了
 
sagaMiddleware.run(mySaga)
//run: 發(fā)送
// 這里是封裝了一個(gè)mySage函數(shù)作為修改狀態(tài)的函數(shù)
 
export default store

接下來(lái)具體介紹saga如何修改狀態(tài)

在redux-saga中,修改狀態(tài)時(shí)使用Genarator函數(shù)實(shí)現(xiàn)的

import { call, put, takeLatest } from 'redux-saga/effects'
 
import { getBannerList, getProList } from '../api/home'
 
//  redux-saga    --->    必須與generator函數(shù)一起使用
 
function * getBannerListAction() {
  const res = yield call(getBannerList) //call--調(diào)用函數(shù)
  yield put({
    type: 'CHANGE_BANNER_LIST',
    payload: res.data
  })
}
function * getProListAction (action){
  const res = yield call(getProList, action.payload)
  yield put({
    type: 'CHANGE_PRO_LIST',
    payload: res.data
  })
}
 
function * mySaga () {
  yield takeLatest('REQUEST_BANNER_LIST', getBannerListAction)
  yield takeLatest('REQUEST_PRO_LIST', getProListAction)
}
 
export default mySaga

  如果看不懂上面,別怕??催@里

// mysaga文件中我們定義了發(fā)送的方式
import { takeLatest } from 'redux-saga/effects'
// takeLatest ---分配任務(wù);在下方。我們自己定義了key并為其分配了事件,這些事件就是store.dispatch()函數(shù)使用的
 
function * getProListAction (action){
  const res = yield call(getProList, action.payload)
  yield put({
    type: 'CHANGE_PRO_LIST',
    payload: res.data
  })
}
function * mySaga () {
  yield takeLatest('REQUEST_PRO_LIST', getProListAction)
}
 
//  我們以后再想修改狀態(tài)的時(shí)候就不需要使用store.dispatch()這樣修改了
//  可以使用這個(gè)文件中定義的key值進(jìn)行修改
 
//  我們?cè)诮M件的connect中這樣定義自定義函數(shù),直接根據(jù)key值調(diào)用這里的修改方法
dispatch => {
    dispatch({ type: 'REQUEST_PRO_LIST'})
}
 
 
// put, call
//  call ---> 含義是調(diào)用
//  put ---> 含義是推,把當(dāng)前的action推到下一個(gè)去執(zhí)行(隊(duì)列)。
 
yield put(action)
yield call(fn)

  以上就是本人結(jié)合各種文檔對(duì)于React常用的狀態(tài)管理器的一些理解,如果有說(shuō)錯(cuò)的地方,還希望大家能指出,我們共同進(jìn)步。

  除了以上這些狀態(tài)管理器,市面上還有一些工具,MobX,Umi,Dva,這些有時(shí)間的話本人也會(huì)整理出來(lái)與大家共享。

到此這篇關(guān)于對(duì)于React各種狀態(tài)管理器的解讀的文章就介紹到這了,更多相關(guān)React狀態(tài)管理器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React封裝自定義Hook捕獲所有錯(cuò)誤的實(shí)現(xiàn)方法

    React封裝自定義Hook捕獲所有錯(cuò)誤的實(shí)現(xiàn)方法

    在 React 開(kāi)發(fā)中,錯(cuò)誤處理是確保應(yīng)用穩(wěn)定性和用戶體驗(yàn)的重要部分,React 提供了多種錯(cuò)誤捕獲方式,包括錯(cuò)誤邊界**等,本文將詳細(xì)介紹這些方法,并展示如何封裝一個(gè)能夠捕獲所有同步和異步錯(cuò)誤的自定義 Hook,需要的朋友可以參考下
    2024-12-12
  • webpack入門+react環(huán)境配置

    webpack入門+react環(huán)境配置

    webpack是一個(gè)前端資源模塊化管理和打包工具,說(shuō)白了就是方便我們管理自己的常用的一些代碼,比如你開(kāi)發(fā)中用到sass以及jade同時(shí)用到es6,開(kāi)發(fā)時(shí)你不可能改動(dòng)某個(gè)地方就挨個(gè)命令去轉(zhuǎn)換再到瀏覽器去看效果,那樣效率是非常低的。所以webpack幫我們省去了那些多余的步驟。
    2017-02-02
  • react render props模式實(shí)現(xiàn)組件復(fù)用示例

    react render props模式實(shí)現(xiàn)組件復(fù)用示例

    本文主要介紹了react render props模式實(shí)現(xiàn)組件復(fù)用示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • react代碼分割的三種實(shí)現(xiàn)方法

    react代碼分割的三種實(shí)現(xiàn)方法

    React代碼分割主要是為了優(yōu)化首屏加載速度,避免一次性加載整個(gè)應(yīng)用,把代碼拆分成多個(gè)bundle,按需加載,下面就一起來(lái)了解一下,感興趣的可以了解一下
    2025-09-09
  • 詳解基于webpack搭建react運(yùn)行環(huán)境

    詳解基于webpack搭建react運(yùn)行環(huán)境

    本篇文章主要介紹了詳解基于webpack搭建react運(yùn)行環(huán)境,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • react中form.setFieldvalue數(shù)據(jù)回填時(shí) value和text不對(duì)應(yīng)的問(wèn)題及解決方法

    react中form.setFieldvalue數(shù)據(jù)回填時(shí) value和text不對(duì)應(yīng)的問(wèn)題及解決方法

    這篇文章主要介紹了react中form.setFieldvalue數(shù)據(jù)回填時(shí) value和text不對(duì)應(yīng)的問(wèn)題及解決方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • ahooks useVirtualList 封裝虛擬滾動(dòng)列表

    ahooks useVirtualList 封裝虛擬滾動(dòng)列表

    這篇文章主要為大家介紹了ahooks useVirtualList 封裝虛擬滾動(dòng)列表詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 解讀react的onClick自動(dòng)觸發(fā)等相關(guān)問(wèn)題

    解讀react的onClick自動(dòng)觸發(fā)等相關(guān)問(wèn)題

    這篇文章主要介紹了解讀react的onClick自動(dòng)觸發(fā)等相關(guān)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 在react中使用vue的狀態(tài)管理的方法示例

    在react中使用vue的狀態(tài)管理的方法示例

    這篇文章主要介紹了在react中使用vue的狀態(tài)管理的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Reactjs?錯(cuò)誤邊界優(yōu)雅處理方法demo

    Reactjs?錯(cuò)誤邊界優(yōu)雅處理方法demo

    這篇文章主要為大家介紹了Reactjs?錯(cuò)誤邊界優(yōu)雅處理方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12

最新評(píng)論

博湖县| 盘山县| 崇义县| 石河子市| 庆云县| 中江县| 蒙城县| 高雄市| 沾化县| 建宁县| 孟连| 宁波市| 湾仔区| 武隆县| 长治县| 正阳县| 新昌县| 天津市| 云浮市| 东城区| 桓台县| 简阳市| 清镇市| 松阳县| 芮城县| 乐都县| 楚雄市| 湘阴县| 开原市| 乌兰察布市| 高碑店市| 亚东县| 延寿县| 保亭| 如东县| 平塘县| 佛坪县| 九寨沟县| 三门县| 牙克石市| 蒙城县|