redux最基本使用
基本使用
1、创建Store阶段
从redux中引入引入createStore,createStore接收reducer函数,createStore会返回Store。
reducer函数用于根据action的type返回不同的state,当reducer传给createStore时会执行一次reducer,此时state为undefined,所以需要赋初始值initialState,用于返回初次的state。
redux/index.js代码如下:
import { createStore } from 'redux'
const initialState = {
age: 18
}
const reducer = function (state = initialState, action) {
// 创建完Store会执行一次reducer,这时state是undefined,所以需要赋初始值initialState
switch (action.type) {
case 'change_age':
return { ...state, age: action.age }
default:
return state
}
}
export const Store = createStore(reducer)
2、使用
我们首先会从上面的文件中引入Store,通过 Store.getState().[属性名] 拿到具体的state值。
如果想更改state的值,我们需要先定义出一个action对象,将其传递给Store.dispatch方法,然后就会执行前面定义的reducer方法,根据action的type返回新的state。
当state更新,页面并不会变化(react更新逻辑:state或者props改变,或者执行forceupdate),我们需要使用Store.subscribe进行订阅监听,在这个回调中完成更新页面的操作,比如执行setAge。
具体代码如下:
import { useEffect, useState } from 'react'
import { Store } from './redux'
function App() {
const [age, setAge] = useState(Store.getState().age)
useEffect(() => {
// 当state发生变化时,视图不会变化,需要监听state变化后手动更新视图
const unSubscribe = Store.subscribe(() => {
setAge(Store.getState().age)
})
return () => {
unSubscribe()
}
})
function addAge() {
const action = { type: 'change_age', age: Store.getState().age + 1 }
// action是个对象,传递给dispatch
Store.dispatch(action)
}
return (
<div className='App'>
{Store.getState().age}
<button onClick={addAge}>增加</button>
</div>
)
}
export default App
基本概念
通过上面两段代码,我们认识了redux中几个重要的概念,即Store、state、action、reducer、dispatch、subscribe。
- Store
Store是redux的核心,用它存储state。
由于遵循“单一数据源”的原则,我们只创建了一个Store。而像pinia这类库,为了分模块有创建多个Store。至于redux如何分模块后续介绍。
- state
状态state就是我们存储的数据对象,我们不会直接去修改state内部的数据,而是通过reducer返回更新后一个新的state。
- action
通常action是一个对象,包含type和本次修改的值,reducer会根据不同的type返回处理并返回新的state。
action也可以是函数,这需要中间件来参与拦截完成预先的操作(比如后面介绍的redux-thunk)。
- reducer
reducer是redux中主要的逻辑处理的方法,当我们调用dispatch时,redux会将当前的state和本次的action传递给reducer函数,reducer函数根据action.type返回新的state。
我们期望reducer是一个纯函数。
- dispatch
Store.dispatch方法是修改state的开始的地方,他接收action,从而更新state。
- subscribe
目前,当state发生变化,我们会在Store.subscribe这个回调中完成更新页面的操作。后面会使用react-redux库中的connect,来将你需要的state映射到props上,从而省略手动调用subscribe的步骤。
基本流程
至此,我们能总结出一个redux更新state并更新页面的基本流程,如图(王红元老师画的)
基本规范
官方推荐我们创建4个文件来分解第一段代码,分别是index.js \ reducer.js \ actionCreators.js \ constant.js
以下是详细的步骤
1、index.js:导入createStore,和reducer。将reducer丢给createStore后会创建出一个store
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer) //createStore接收reducer,用来创建store
export default store
2、reducer.js
关于reducer.js文件,引入action有关的常量,创建一个初始的state对象,然后写一个reducer函数,这个函数参数是state和action,函数体用switch判断action的type做不同的处理。最后导出这个函数
import * as actionType from './constants'
const initialState = {
num: 23
}
export default function reducer(state = initialState, actions) {
switch (actions.type) {
case actionType.ADD_NUM_ACTION:
return { ...state, num: state.num + actions.num }
case actionType.DESC_NUM_ACTION:
return { ...state, num: state.num - actions.num }
default:
return state
}
}
3、actionCreators.js
actionCreators.js文件,帮助我们创建action。
就是导出一些函数用来创建action对象,减少代码量。action对象包含type和传递的其他变量值。
/* 这里的函数是创建各个action,减少代码 */
import * as actionType from './constants'
export const addNumAction = (num) => ({
type: actionType.ADD_NUM_ACTION,
num//可以统一写成value
})
export const descNumAction = (num) => ({
type: actionType.DESC_NUM_ACTION,
num
})
4、constants.js,存放reducer和创建action函数需要的常量【避免写错】
export const ADD_NUM_ACTION ='addNumAction'
export const DESC_NUM_ACTION ='descNumAction'
5、使用。引入store和创建action的函数
import React, { PureComponent } from 'react'
import store from '../store'
import { addNumAction } from '../store/actionCreators'
export class Home extends PureComponent {
componentDidMount() {
//
store.subscribe(() => {
const storeState = store.getState()
this.setState({
counter: storeState.num,
})
})
}
state = {
counter: store.getState().num,
}
addNum(num) {
store.dispatch(addNumAction(num))
}
render() {
const { counter } = this.state
return (
<div>
{counter}
<button onClick={() => { this.addNum(1) }}> +1
</button>
</div>
)
}
}
export default Home
end
主要介绍了redux这个库的基本使用,有助于理解redux中的基本概念,为后面学习打好基础,哈哈。
在真正项目运用中,我们会使用react-redux或者rtk这两个库,下篇文章介绍。