一文詳解React?Redux使用方法
一、理解JavaScript純函數(shù)
1.1 純函數(shù)的概念
純函數(shù)的維基百科定義:
- 在程序設(shè)計(jì)中,若一個(gè)函數(shù)符合以下條件,那么這個(gè)函數(shù)被稱(chēng)為純函數(shù)
- 此函數(shù)在相同的輸入值時(shí),需產(chǎn)生相同的輸出
- 函數(shù)的輸出和輸入值以外的其他隱藏信息或狀態(tài)無(wú)關(guān),也和由I/O設(shè)備產(chǎn)生的外部輸出無(wú)關(guān)
- 該函數(shù)不能有語(yǔ)義上可觀察的函數(shù)副作用,諸如“觸發(fā)事件”,使輸出設(shè)備輸出,或更改輸出值以外物件的內(nèi)容等
純函數(shù)概念,總結(jié)如下:
- 確定的輸入,一定會(huì)產(chǎn)生確定的輸出
- 函數(shù)在執(zhí)行過(guò)程中,不能產(chǎn)生副作用
案例(數(shù)組的兩個(gè)方法):
- slice:slice截取數(shù)組時(shí)不會(huì)對(duì)原數(shù)組進(jìn)行任何操作,而是生成一個(gè)新的數(shù)組
- splice:splice截取數(shù)組, 會(huì)返回一個(gè)新的數(shù)組,也會(huì)對(duì)原數(shù)組進(jìn)行修改
1.2 副作用概念的理解
什么是副作用?
- 副作用(side effect)表示在執(zhí)行一個(gè)函數(shù)時(shí),除了返回函數(shù)值之外,還對(duì)調(diào)用函數(shù)產(chǎn)生了附加的影響,比如修改了全局變量,修改參數(shù)或者改變外部的存儲(chǔ)
純函數(shù)在執(zhí)行的過(guò)程中就是不能產(chǎn)生這樣的副作用:
- 副作用往往是產(chǎn)生bug的 “溫床”
1.3 純函數(shù)在函數(shù)式編程的重要性
為什么純函數(shù)在函數(shù)式編程中非常重要呢?
- 可以安心的編寫(xiě)和安心的使用
- 在寫(xiě)的時(shí)候保證了函數(shù)的純度,只是單純實(shí)現(xiàn)自己的業(yè)務(wù)邏輯即可,不需要關(guān)心傳入的內(nèi)容是如何獲得的或者依賴(lài)其他的外部變量是否已經(jīng)發(fā)生了修改
- 在用的時(shí)候,確定的輸入內(nèi)容不會(huì)被任意篡改,并且自己確定的輸入,一定會(huì)有確定的輸出
- React中就要求我們無(wú)論是函數(shù)還是class聲明一個(gè)組件,這個(gè)組件都必須像純函數(shù)一樣,保護(hù)它們的
props不被修改 - 在下面的redux中,reducer也被要求是一個(gè)純函數(shù)
二、Redux的核心思想
2.1 為什么需要 Redux
JavaScript開(kāi)發(fā)的應(yīng)用程序變得越來(lái)越復(fù)雜:
- JavaScript需要管理的狀態(tài)越來(lái)越多,越來(lái)越復(fù)雜
- 這些狀態(tài)包括服務(wù)器返回的數(shù)據(jù)、緩存數(shù)據(jù)、用戶(hù)操作產(chǎn)生的數(shù)據(jù)等等,也包括一些UI的狀態(tài),比如某些元素是否被選中,是否顯示加載動(dòng)效,當(dāng)前分頁(yè)
管理不斷變化的state是非常困難的:
- 狀態(tài)之間相互會(huì)存在依賴(lài),一個(gè)狀態(tài)的變化會(huì)引起另一個(gè)狀態(tài)的變化,View頁(yè)面也有可能會(huì)引起狀態(tài)的變化
- 當(dāng)應(yīng)用程序復(fù)雜時(shí),state在什么時(shí)候,因?yàn)槭裁丛蚨l(fā)生了變化,發(fā)生了怎么樣的變化,會(huì)變得非常難以控制和追蹤
React是在視圖層幫助我們解決了DOM的渲染過(guò)程,但是State依然是留給我們自己來(lái)管理:
- 無(wú)論是組件定義自己的state,還是組件之間的通信通過(guò)props進(jìn)行傳遞;也包括通過(guò)Context進(jìn)行數(shù)據(jù)之間的共享
- React主要負(fù)責(zé)幫助我們管理視圖,state如何維護(hù)最終還是我們自己來(lái)決定

- Redux就是一個(gè)幫助我們管理State的容器:Redux是JavaScript的狀態(tài)容器,提供了可預(yù)測(cè)的狀態(tài)管理
- Redux除了和React一起使用之外,它也可以和其他界面庫(kù)一起來(lái)使用(比如Vue、小程序),并且它非常小(包括依賴(lài)在內(nèi),只有2kb)
2.2 Redux的核心概念
2.2.1 store
可以定義一些初始化的數(shù)據(jù),通過(guò) reducer 傳入
2.2.2 action
- store 中數(shù)據(jù)的變化,必須通過(guò)派發(fā)(dispatch)action來(lái)更新
- action是一個(gè)普通的JavaScript對(duì)象,用來(lái)描述這次更新的type和content
2.2.3 reducer
將傳入的state和action結(jié)合起來(lái)生成一個(gè)新的state
2.3 Redux的三大原則
2.3.1 單一數(shù)據(jù)源
- 整個(gè)應(yīng)用程序的state被存儲(chǔ)在一顆object tree中,并且這個(gè)object tree只存儲(chǔ)在一個(gè) store 中
- Redux并沒(méi)有強(qiáng)制讓我們不能創(chuàng)建多個(gè)Store,但是那樣做并不利于數(shù)據(jù)的維護(hù)
- 單一的數(shù)據(jù)源可以讓整個(gè)應(yīng)用程序的state變得方便維護(hù)、追蹤、修改
2.3.2 State是只讀的
- 唯一修改State的方法是觸發(fā)action,不要試圖在其他地方通過(guò)任何的方式來(lái)修改State
- 這樣就確保了View或網(wǎng)絡(luò)請(qǐng)求都不能直接修改state,它們只能通過(guò)action來(lái)描述自己想要如何修改state
- 這樣可以保證所有的修改都被集中化處理,并且按照嚴(yán)格的順序來(lái)執(zhí)行,所以不需要擔(dān)心race condition(竟態(tài))的問(wèn)題
2.3.3 使用純函數(shù)來(lái)執(zhí)行修改
- 通過(guò)reducer將 舊state和 actions聯(lián)系在一起,并且返回一個(gè)新的State
- 隨著應(yīng)用程序的復(fù)雜度增加,可以將reducer拆分成多個(gè)小的reducers,分別操作不同state tree的一部分
- 但是所有的reducer都應(yīng)該是純函數(shù),不能產(chǎn)生任何的副作用
2.4 Redux 工作流程
建議看完Redux基本使用后再來(lái)看這幅圖:

三、Redux基本使用
注意:以下 3 部分代碼在 node 環(huán)境下
- 需要安裝redux:
npm install redux
補(bǔ)充:node中對(duì)ES6模塊化的支持
node v13.2.0開(kāi)始,對(duì)ES6模塊化提供了支持:
node v13.2.0之前,需要進(jìn)行如下操作:
- 在package.json中添加屬性: "type": "module"
- 在執(zhí)行命令中添加如下選項(xiàng):node --experimental-modules src/index.js
node v13.2.0之后,只需要進(jìn)行如下操作:
- 在package.json中添加屬性: "type": "module"
- 注意:導(dǎo)入文件時(shí),需要跟上
.js后綴名
3.1 創(chuàng)建Store的過(guò)程
定義reducer:必須是一個(gè)純函數(shù),不要直接修改state
createStore 傳入 reducer
const { createStore } = require('redux')
// 初始化的數(shù)據(jù)
const initialState = {
name: '李雷',
counter: 100
}
// 定義reducer函數(shù):純函數(shù)
// 兩個(gè)參數(shù):
// 參數(shù)一:store中目前保存的state
// 參數(shù)二:本次需要更新的action(dispatch傳入的action)
// 返回值:返回值會(huì)作為store之后存儲(chǔ)的state
function reducer(state = initialState, action) {
switch (action.type) {
case 'change_name':
return { ...state, name: action.name }
case 'add_numer':
return { ...state, counter: state.counter + action.num }
default:
return state
}
}
// 創(chuàng)建store
const store = createStore(reducer)
module.exports = store3.2 dispatch派發(fā)action
- store 通過(guò) dispatch 來(lái)派發(fā) action
- 通常會(huì)有 type 屬性,也可以攜帶其他數(shù)據(jù)
const store = require('./store')
console.log(store.getState()) // { name: '李雷', counter: 100 }
// 修改store中的數(shù)據(jù):必須action
const nameAction = { type: 'change_name', name: '韓梅梅' }
store.dispatch(nameAction)
console.log(store.getState()) // { name: '韓梅梅', counter: 100 }
const nameAction2 = { type: 'change_name', name: '夏洛' }
store.dispatch(nameAction2)
console.log(store.getState()) // { name: '夏洛', counter: 100 }
// 修改counter
const counterAction = { type: 'add_numer', num: 10 }
store.dispatch(counterAction)
console.log(store.getState()) // { name: '夏洛', counter: 110 }3.3 subscribe定位state
store.subscribe()傳入一個(gè)函數(shù)能夠監(jiān)聽(tīng)數(shù)據(jù)的變化store.subscribe()會(huì)返回一個(gè)函數(shù),執(zhí)行該函數(shù)取消監(jiān)聽(tīng)
const store = require('./store')
const unSubscribe = store.subscribe(() => {
console.log('訂閱數(shù)據(jù)的變化:', store.getState())
})
// 修改store中的數(shù)據(jù):必須action
store.dispatch({ type: 'change_name', name: '韓梅梅' })
store.dispatch({ type: 'change_name', name: '夏洛' })
// 取消訂閱
unSubscribe()
// 修改counter
store.dispatch({ type: 'add_numer', num: 10 })3.4 代碼優(yōu)化
- 優(yōu)化方向:
- action的創(chuàng)建放到一個(gè)函數(shù)中
- 抽取到actionCreators.js文件中
- 所有的字符串常量放到constants.js文件
- reducer函數(shù)和初始化值, 放到reducer.js文件
- index.js中創(chuàng)建store和導(dǎo)出store
示例:
actionCreators.js
const { ADD_NUMBER, CHANGE_NAME } = require("./constants")
const changeNameAction = (name) => ({
type: CHANGE_NAME,
name
})
const addNumberAction = (num) => ({
type: ADD_NUMBER,
num
})
module.exports = {
changeNameAction,
addNumberAction
}const ADD_NUMBER = "add_number"
const CHANGE_NAME = "change_name"
module.exports = {
ADD_NUMBER,
CHANGE_NAME
}const { CHANGE_NAME, ADD_NUMBER } = require('./constants')
// 初始化的數(shù)據(jù)
const initialState = {
name: '李雷',
counter: 100
}
function reducer(state = initialState, action) {
switch (action.type) {
case CHANGE_NAME:
return { ...state, name: action.name }
case ADD_NUMBER:
return { ...state, counter: state.counter + action.num }
default:
return state
}
}
module.exports = reducerconst { createStore } = require('redux')
const reducer = require('./reducer')
// 創(chuàng)建store
const store = createStore(reducer)
module.exports = storeconst store = require('./store')
const { changeNameAction, addNumberAction } = require('./store/actionCreators')
store.dispatch(changeNameAction('獨(dú)孤月'))
store.dispatch(addNumberAction(100))
console.log(store.getState()) // { name: '獨(dú)孤月', counter: 200 }- constants.js
- reducer.js
- index.js
- util.js 中使用
四、Redux 在 React中使用
4.1 先來(lái)一個(gè)案例
有兩個(gè)組件,組件上展示同一個(gè)counter,并且兩者能夠?qū)ounter進(jìn)行操作

- 創(chuàng)建redux對(duì)應(yīng)的store文件夾
actionCreators.js
import * as actionTypes from './constants'
export const addNumberAction = (num) => ({
type: actionTypes.ADD_NUMBER,
num
})
export const subNumberAction = (num) => ({
type: actionTypes.SUB_NUMBER,
num
})constants.js
export const ADD_NUMBER = "add_number" export const SUB_NUMBER = "sub_number"
reducer.js
import * as actionTypes from './constants'
const initialState = {
counter: 100
}
function reducer(state = initialState, action) {
switch (action.type) {
case actionTypes.ADD_NUMBER:
return { ...state, counter: state.counter + action.num }
case actionTypes.SUB_NUMBER:
return { ...state, counter: state.counter - action.num }
default:
return state
}
}
export default reducerindex.js
import { createStore } from "redux"
import reducer from "./reducer"
const store = createStore(reducer)
export default store組件中使用:
import React, { PureComponent } from 'react'
// 引入store
import store from '../store'
import { addNumberAction } from '../store/actionCreators'
export default class Home extends PureComponent {
constructor() {
super()
this.state = {
counter: store.getState().counter
}
}
componentDidMount() {
store.subscribe(() => {
const state = store.getState()
this.setState({ counter: state.counter })
})
}
addNumber(num) {
store.dispatch(addNumberAction(num))
}
render() {
const { counter } = this.state
return (
<div>
<h2>Home Counter: {counter}</h2>
<div>
<button onClick={e => this.addNumber(1)}>+1</button>
<button onClick={e => this.addNumber(5)}>+5</button>
<button onClick={e => this.addNumber(8)}>+8</button>
</div>
</div>
)
}
}import React, { PureComponent } from 'react'
// 引入store
import store from '../store'
import { subNumberAction } from '../store/actionCreators'
export default class Profile extends PureComponent {
constructor() {
super()
this.state = {
counter: store.getState().counter
}
}
componentDidMount() {
store.subscribe(() => {
const state = store.getState()
this.setState({ counter: state.counter })
})
}
subNumber(num) {
store.dispatch(subNumberAction(num))
}
render() {
const { counter } = this.state
return (
<div>
<h2>Profile Counter: {counter}</h2>
<div>
<button onClick={e => this.subNumber(1)}>-1</button>
<button onClick={e => this.subNumber(5)}>-5</button>
<button onClick={e => this.subNumber(8)}>-8</button>
</div>
</div>
)
}
}- componentDidMount生命周期
- store.subscribe(() => {}) => this.state => render
- 修改數(shù)據(jù):store.dispatch(addNumberAction(num))
- Home.jsx
- Profile.jsx
4.2 react-redux使用
安裝:npm install react-redux
在使用時(shí)在入口文件中導(dǎo)入 Provider,傳入 store
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import store from './store'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);在 About 組件中使用:
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { addNumberAction, subNumberAction } from '../store/actionCreators'
export class About extends PureComponent {
clacNumber(num, isAdd) {
if(isAdd) {
this.props.addNumber(num)
} else {
this.props.subNumber(num)
}
}
render() {
const { counter } = this.props
return (
<div>
<h2>About Counter: {counter}</h2>
<button onClick={e => this.clacNumber(6, true)}>+6</button>
<button onClick={e => this.clacNumber(9, true)}>+9</button>
<button onClick={e => this.clacNumber(6, false)}>-6</button>
<button onClick={e => this.clacNumber(9, false)}>-9</button>
</div>
)
}
}
// connect() 返回值是一個(gè)高階組件
// function mapStateToProps(state) {
// return {
// counter: state.counter
// }
// }
const mapStateToProps = (state) => ({ counter: state.counter })
const mapDispatchToProps = (dispatch) => ({
addNumber: num => dispatch(addNumberAction(num)),
subNumber: num => dispatch(subNumberAction(num))
})
export default connect(mapStateToProps, mapDispatchToProps)(About)
connect():
- 傳入的第一個(gè)函數(shù)是映射當(dāng)前組件所需要的數(shù)據(jù)(store中可能有很多數(shù)據(jù),比如books、counter,而此處只需要counter)
- 傳入的第二個(gè)函數(shù)是映射
dispatch到 props - 返回一個(gè)高階組件
4.3 組件中的異步操作
4.3.1 類(lèi)組件生命周期中請(qǐng)求數(shù)據(jù)
- 在class組件的componentDidMount中發(fā)送請(qǐng)求
通過(guò)發(fā)起action將請(qǐng)求的數(shù)據(jù)保存到store中
action方法:
export const changeBannersAction = (banners) => ({
type: actionTypes.CHANGE_BANNERS,
banners
})
export const changeRecommendsAction = (recommends) => ({
type: actionTypes.CHANGE_RECOMMENDS,
recommends
})import * as actionTypes from './constants'
const initialState = {
counter: 100,
banners: [],
recommends: []
}
function reducer(state = initialState, action) {
switch (action.type) {
case actionTypes.CHANGE_BANNERS:
return { ...state, banners: action.banners }
case actionTypes.CHANGE_RECOMMENDS:
return { ...state, recommends: action.recommends }
default:
return state
}
}
export default reducerimport React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import axios from 'axios'
import { changeBannersAction, changeRecommendsAction } from '../store/actionCreators'
export class Category extends PureComponent {
componentDidMount() {
// 發(fā)送請(qǐng)求
axios.get('http://123.207.32.32:8000/home/multidata').then(res => {
const banners = res.data.data.banner.list
const recommends = res.data.data.recommend.list
this.props.changeBanners(banners)
this.props.changeRecommends(recommends)
})
}
render() {
return (
<div>
<h2>Category Page</h2>
</div>
)
}
}
const mapDispatchToProps = (dispacth) => ({
changeBanners: banners => dispacth(changeBannersAction(banners)),
changeRecommends: recommends => dispacth(changeRecommendsAction(recommends))
})
export default connect(null, mapDispatchToProps)(Category)- reducer
- category組件
4.3.2 使用中間件
上面的代碼有一個(gè)缺陷:
- 我們必須將網(wǎng)絡(luò)請(qǐng)求的異步代碼放到組件的生命周期中來(lái)完成
- 事實(shí)上,網(wǎng)絡(luò)請(qǐng)求到的數(shù)據(jù)也屬于狀態(tài)管理的一部分,更好的一種方式應(yīng)該是將其也交給redux來(lái)管理

如何將異步請(qǐng)求交給 Redux?
- 一個(gè)普通的action,返回的是一個(gè)對(duì)象
{ type: CHANGE_COUNTER, num: 10 } - 對(duì)象中是無(wú)法直接拿到服務(wù)器請(qǐng)求到的異步數(shù)據(jù)的,但是如果返回一個(gè)函數(shù)呢?
- 返回一個(gè)函數(shù),然后在組件中發(fā)起 Action 的時(shí)候,執(zhí)行這個(gè)函數(shù)是不是就能夠拿到數(shù)據(jù)了呢?。?!
- ?。?! 普通的 action 不能返回函數(shù),可以借助中間件來(lái)增強(qiáng)一下,讓他支持返回一個(gè)函數(shù),官網(wǎng)推薦的中間件:redux-thunk
- 中間件的目的:是在dispatch的action和最終達(dá)到的reducer之間,擴(kuò)展一些自己的代碼
redux-thunk 做了什么呢
- 讓
dispatch(action函數(shù))中的action可以是一個(gè)函數(shù); - 該函數(shù)會(huì)被調(diào)用,并且會(huì)傳給這個(gè)函數(shù)一個(gè)dispatch函數(shù)和getState函數(shù);
- dispatch函數(shù)用于之后再次派發(fā)action
- getState函數(shù)考慮到我們之后的一些操作需要依賴(lài)原來(lái)的狀態(tài),用于獲取之前的一些狀態(tài)
代碼演示:
import { createStore, applyMiddleware } from "redux"
import thunk from "redux-thunk"
import reducer from "./reducer"
// 正常情況下 store.dispatch(object)
// 想要派發(fā)函數(shù) store.dispatch(function)
// applyMiddleware 可以傳入多個(gè)中間件,","隔開(kāi)
const store = createStore(reducer, applyMiddleware(thunk))
export default storeimport * as actionTypes from './constants'
import axios from 'axios'
export const changeBannersAction = (banners) => ({
type: actionTypes.CHANGE_BANNERS,
banners
})
export const changeRecommendsAction = (recommends) => ({
type: actionTypes.CHANGE_RECOMMENDS,
recommends
})
export const fetchHomeMultidataAction = () => {
// 如果是一個(gè)普通的action,需要返回action對(duì)象
// 問(wèn)題: 對(duì)象中不能直接拿到從服務(wù)器請(qǐng)求的異步數(shù)據(jù)
// redux 不允許返回一個(gè)函數(shù),需要中間件
return (dispatch, getState) => {
// console.log(getState().counter) // 100
// 進(jìn)行異步操作: 網(wǎng)絡(luò)請(qǐng)求
axios.get('http://123.207.32.32:8000/home/multidata').then(res => {
const banners = res.data.data.banner.list
const recommends = res.data.data.recommend.list
// dispatch({type: actionTypes.CHANGE_BANNERS, banners})
// dispatch({type: actionTypes.CHANGE_RECOMMENDS, recommends})
dispatch(changeBannersAction(banners))
dispatch(changeRecommendsAction(recommends))
})
}
}import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { fetchHomeMultidataAction } from '../store/actionCreators'
export class Category extends PureComponent {
componentDidMount() {
this.props.fetchHomeMultidata()
}
render() {
return (
<div>
<h2>Category Page</h2>
</div>
)
}
}
const mapStateToProps = state => ({
counter: state.counter
})
const mapDispatchToProps = (dispacth) => ({
fetchHomeMultidata: () => dispacth(fetchHomeMultidataAction())
})
export default connect(mapStateToProps, mapDispatchToProps)(Category)- store(index.js) 中引入thunk
- actionCreators.js
- 組件中使用
4.4 redux-devtools
redux可以方便的對(duì)狀態(tài)進(jìn)行跟蹤和調(diào)試
- redux官網(wǎng)提供了redux-devtools的工具
- 利用這個(gè)工具,可以知道每次狀態(tài)是如何被修改的,修改前后的狀態(tài)變化等等
安裝該工具需要兩步:
- 在對(duì)應(yīng)的瀏覽器中安裝相關(guān)的插件(比如Chrome瀏覽器擴(kuò)展商店中搜索Redux DevTools即可)
- 在redux中繼承devtools的中間件
默認(rèn)該工具是未開(kāi)啟的,開(kāi)發(fā)環(huán)境開(kāi)啟需要進(jìn)行配置,生產(chǎn)環(huán)境千萬(wàn)千萬(wàn)不要打開(kāi)哦!??!
import { createStore, applyMiddleware, compose } from "redux"
import thunk from "redux-thunk"
import reducer from "./reducer"
// redux-devtools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({trace: true}) || compose;
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)))
export default store
復(fù)制代碼4.5 模塊拆分
正常情況下,我們的 store 中應(yīng)該是有不同狀態(tài)的數(shù)據(jù),比如:購(gòu)物車(chē)、用戶(hù)信息等等, 如果將所有的狀態(tài)都放到一個(gè)reducer中進(jìn)行管理,隨著項(xiàng)目的日趨龐大,必然會(huì)造成代碼臃腫、難以維護(hù)。因此,我們可以對(duì)reducer進(jìn)行拆分。
以上面提到的案例為例,抽取一個(gè) counter 的reducer和一個(gè) home 的reducer,再將其合并起來(lái)
分不同的模塊,每個(gè)模塊都包含自己的核心:
>reducer:接收action對(duì)象,返回最新的state
- constants:定義常量數(shù)據(jù)
- actioncreators:定義創(chuàng)建action對(duì)象的函數(shù)
- index:導(dǎo)出reducer

在 index.js 中導(dǎo)入每一個(gè)模塊的內(nèi)容,通過(guò)combineReducers合并之后放入createStore
import { createStore, applyMiddleware, compose, combineReducers } from "redux"
import thunk from "redux-thunk"
import counterReducer from './counter'
import homeReducer from './home'
import userReducer from './user'
// 將reducer合并到一起
const reducer = combineReducers({
counter: counterReducer,
home: homeReducer,
user: userReducer
})
// redux-devtools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({trace: true}) || compose;
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)))
export default storecombineReducers 如何實(shí)現(xiàn)合并呢?
- 事實(shí)上,它是將我們傳入的reducers合并到一個(gè)對(duì)象中,最終返回一個(gè)combination的函數(shù)(相當(dāng)于我們的reducer函數(shù)了)
- 在執(zhí)行combination函數(shù)的過(guò)程中,它會(huì)通過(guò)判斷前后返回的數(shù)據(jù)是否相同來(lái)決定返回之前的state還是新的state
- 新的state會(huì)觸發(fā)訂閱者發(fā)生對(duì)應(yīng)的刷新,而舊的state可以有效的阻止訂閱者發(fā)生刷新
// combineReducers 原理
function reducer(state = {}, action) {
// 返回一個(gè)對(duì)象,store中的state
return {
counter: counterReducer(state.counter, action),
home: homeReducer(state.home, action),
user: userReducer(state.user, action)
}
}到此這篇關(guān)于一文詳解React Redux使用方法的文章就介紹到這了,更多相關(guān)React Redux使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于React實(shí)現(xiàn)無(wú)限滾動(dòng)表格
以文本為例,為了實(shí)現(xiàn)無(wú)限循環(huán)的視覺(jué)效果,我們需要準(zhǔn)備兩段相同的文本,并讓第二段文本的頭部銜接在第一段文本的尾部,同時(shí),為兩段文本設(shè)置相同的滾動(dòng)動(dòng)畫(huà),本文給大家介紹了基于React實(shí)現(xiàn)無(wú)限滾動(dòng)表格,需要的朋友可以參考下2023-11-11
使用React+SpringBoot開(kāi)發(fā)一個(gè)協(xié)同編輯的表格文檔實(shí)現(xiàn)步驟
隨著云計(jì)算和團(tuán)隊(duì)協(xié)作的興起,協(xié)同編輯成為了許多企業(yè)和組織中必不可少的需求,本文小編就將為大家介紹如何使用React+SpringBoot簡(jiǎn)單的開(kāi)發(fā)一個(gè)協(xié)同編輯的表格文檔,感興趣的朋友一起看看吧2023-11-11
React Native:react-native-code-push報(bào)錯(cuò)的解決
這篇文章主要介紹了React Native:react-native-code-push報(bào)錯(cuò)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
再次談?wù)揜eact.js實(shí)現(xiàn)原生js拖拽效果引起的一系列問(wèn)題
React 起源于 Facebook 的內(nèi)部項(xiàng)目,因?yàn)樵摴緦?duì)市場(chǎng)上所有 JavaScript MVC 框架,都不滿(mǎn)意,就決定自己寫(xiě)一套,用來(lái)架設(shè) Instagram 的網(wǎng)站.本文給大家介紹React.js實(shí)現(xiàn)原生js拖拽效果,需要的朋友一起學(xué)習(xí)吧2016-04-04
Hello?React的組件化方式之React入門(mén)小案例演示
這篇文章主要介紹了Hello?React的組件化方式-React入門(mén)小案例,本文通過(guò)Hello?React的案例,?來(lái)體驗(yàn)一下React開(kāi)發(fā)模式,?以及jsx的語(yǔ)法,需要的朋友可以參考下2022-10-10
react render的原理及觸發(fā)時(shí)機(jī)說(shuō)明
這篇文章主要介紹了react render的原理及觸發(fā)時(shí)機(jī)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02

