文章
问答
冒泡
react中使用redux——第一篇,redux的基本用法

react的状态管理第一篇

  • 听名字,我以为redux是react的官方状态管理(如同vuex),redux并不是react独有的状态管理器,在其他的框架中也能够使用redux进行状态的管理。

Redux 由 Flux 演变而来,但受 Elm 的启发,避开了 Flux 的复杂性。 不管你有没有使用过它们,只需几分钟就能上手 Redux。

  • 三大原则。
    • 单一数据源,所有的状态都在唯一的对象树里面,即只存在于唯一的store,不能存在多个store。
    • state是只读属性,唯一能修改state的方法是触发action,action是一个普通对象,其中type属性是必须的,原因稍后分析。
    • 纯函数执行,reducer是纯函数,接受未修改前的state和action,返回新的state。reducer可以分为多个。
  • 下面是创建reducer的例子,在src/store/index.js创建store。我们直接从代码中学习,只是文字很难看一遍就理解。
第一步,引入创建store的函数
    import { createStore } from 'redux'
第二步,定义reducer
    let countReducer = (state, actions) => {
        console.log(state, actions)
        return state
    }
第三步,生成store
    let store = createStore(countReducer)
第四部,到处
    export default store
  • 组件内接受store(组件相关代码省略,根据个人自由发挥生成自己的组件)
第一步,引入store
    import Store from '../store'
第二步,答应出store
    {console.log(Store)}
第三步,为了观测到变化,组件中定义一个state
state = {
        count: Store.getState().count
}
定义一个修改组件内state.count为store.count的方法
getCount = () => {
    this.setState({
        count: Store.getState().count
    })
}
  • 根据打印结果可知,state是undefined,很简单,我们没有设置初始的state。action也是乱七八糟的组成的字符串,这也很正常,因为我们本身目前也没定义action,redux随机生成的。
  • 下面开始初始化state
1.创建一个初始化数据。
const initialState = {
    count: 1
} 
2.将初始化数据丢给reducer做默认值。
let countReducer = (state = {...initialState}, actions) => {
    console.log(state)
    return state
}
3.组件中进行获取
Store.getState()
  • 此时可以发现,打印出来的state包含了状态,{count: 1}
  • 前面已经实现了store的创建,又实现了初始化state,接下来我们需要做的就是如何去修改count的值。
  • 设置相关的action
dispatch提交的action中有个type属性是必须的,请记住是提交,不是创建的action,对应需要触发的reducer中的方法,在store下面创建一个actions.js文件,用来保存相关的action操作。
第一种方法:常量创建
actions.js中的
const ADD_COUNT = 'ADD_COUNT'
const SUB_COUNT = 'SUB_COUNT'
index.js中引入
import {ADD_COUNT, SUB_COUNT} from './actions'
// reducer中使用
let countReducer = (state = {...initialState}, actions) => {
    switch(actions.type){
        case ADD_COUNT: 
            return Object.assign({}, state, {count: state.count +1})
        case SUB_COUNT: 
            return Object.assign({}, state, {count: state.count - 1})
        default: return state
    }
}

dispatch提交的action中有个type属性是必须的,请记住是提交,不是创建的action

上面中的reducer是用来修改state中的值,返回一个新的state,当提交的dispatch与之对应即会执行对应的修改。

  • 组件中定义两个方法去触发对应的action
引入对应的actions
    import { ADD_COUNT, SUB_COUNT} from '../store/actions'

    add(){
        Store.dispatch({
            type: ADD_COUNT
        })
        this.getCount()
    }
    sub(){
        Store.dispatch({
            type: SUB_COUNT
        })
        this.getCount()
    }

add为提交增加count的action(ADD_COUNT)方法,sub为提交减少count的action(SUB_COUNT)方法。记得需要引入对应的action进行哦。使用常量的方式是为了更好的定位错误,如果直接在reducer中使用字符串也是可以进行触发的,提交的时候type为对应的字符串即可。

但是上面的虽然能提交增加和减少,但是默认都是增加1和减少1,如果我需要传递参数应当如何进行操作呢。

dispatch提交的action中有个type属性是必须的,请记住是提交,不是创建的action
    add(){
        Store.dispatch({
            type: ADD_COUNT,
            value: 20
        })
        this.getCount()
    }
    sub(){
        Store.dispatch({
            type: SUB_COUNT,
            value: 10
        })
        this.getCount()
    }

如上中代码,提交的时候是提交一个对象,type是必须的,对应相应需要触发的action,后面可以传递参数。这里传递的参数是value,因此在reducer中可以使用actions.value提取出我们传递过去的参数,然后进行操作,对应的reducer代码如下:

let countReducer = (state = {...initialState}, actions) => {
    switch(actions.type){
        case ADD_COUNT: 
        console.log(actions)
            return Object.assign({}, state, {count: state.count + actions.value})
        case SUB_COUNT: 
            return Object.assign({}, state, {count: state.count - actions.value})
        default: return state
    }
}

除此之外,我们还可以使用函数的方式来创建相应的actions

创建两个常量
export const ADD_SOME = 'ADD_SOME'
export const SUB_SOME = 'SUB_SOME'
创建对应的生成action的函数(这里的函数必须是满足dispatch提交的模式,所以type是必须的)
export function addSome(value) {
    return {
        type: ADD_SOME,
        value
    }
}
export function subSome(value) {
    return {
        type: SUB_SOME,
        value
    }
}

在reducer中创建对应的改变state的方法

let countReducer = (state = {...initialState}, actions) => {
    switch(actions.type){
        case ADD_COUNT: 
            return Object.assign({}, state, {count: state.count + actions.value})
        case SUB_COUNT: 
            return Object.assign({}, state, {count: state.count - actions.value})
        case SUB_SOME:
            return Object.assign({}, state, {count: state.count - actions.value})
        case ADD_SOME: 
            return Object.assign({}, state, {count: state.count + actions.value})
        default: return state
    }
}

上面修改和常量无差别,主要在reducer中实现对应type为什么值的时候,需要执行什么。

使用的时候会有一些差别,如下所示:

import {addSome, subSome,ADD_COUNT, SUB_COUNT} from '../store/actions'
    addValue(){
        Store.dispatch(addSome(10086))
        this.getCount()
    }
    subValue(){
        Store.dispatch(subSome(-10086))
        this.getCount()
    }

函数创建的方法其实和提交一个对象没有什么区别,只是将提交的对象封装成了一个函数,函数的形参对应传递的参数。需要的时候引入,调用函数,形参传递参数即可,无需再次引入常量,因为常量的type已经封装为函数返回的对象中的属性了。

原本打算一口气写完这个redux的,后面再介绍react-thunk和react-redux,但是量偏大,后续在更新,嘎巴的

redux

关于作者

xlynn
获得点赞
文章被阅读