关于store的结构

今天阅读老项目,重读store的结构,发现比较有意思的事情:

一般store会分为如下几个部分,reducers和actions,当然还有constans,reducers文件夹是reducer的集合,其中一个reducer的代码如下:

const fieldList = (state = {}, action) => {
    switch (action.type) {
        case 'fetchFieldListDone':
            return Object.assign({},  action.res)
        case 'fetchFieldListErr':
            return Object.assign({},  action.res)
        case 'fetchFieldListClear':
            return {}
        default:
            return state
    }
}
export default fieldList

可以看到,reducer本质一个函数,函数的参数为state和action,state是默认值,action是一个对象,包含type和res属性,reducr根据action的type决定采取哪些动作,然后返回新的数据对象。

我们发现reducer中未进行任何亦步操作,只是根据type和res来返回数据。

再看action:

import {get} from '../../utils/ajax'
export const fetchFieldList = (obj,message,context) => {
    return async function (despath) {
        let res;
        try {
            res = await get({url:'/custom/v2/field/cmd/list?gymId='+obj.gymId,token:obj.token},message,context);

            if(res.success&&res.data.rows.length){

            }else {
                message.info('当前还没有场地,请先创建场地',1,()=>{
                    context.props.history.push('/home/fieldList/fieldDetail/add')
                })
            }
            despath({
                type: 'fetchFieldListDone',
                res,
            })
        } catch (e) {
            despath({
                type: 'fetchFieldListErr',
                res
            })
        }


    }
}

action的本质也是一个函数,dispatch配置了thunk-reducer之后,dispatch就以传递函数作为参数了,只不过函数的参数为dispatch,这样我们就可以将亦步操作放到函数中执行了,执行问候调用dipatch。有点蒙、、、

 

action是一个函数,函数执行后返回一个特殊的函数,这里将其命名为action可执行函数,在action可执行函数中我们可以执行异步操作,得到结果后,用dispatch将其传递到reducer,然后更改数据。

 

我这里要准备一个教练列表数据,

1、首先我要建立一个reducer,教练类表数据的reducer,定义根据不同的type返回不同的数据

2、然后建立一个action,action可执行函数的内部获取教练数据列表,根据结果向dispatch传递不同的type参数。

在深入一下,我们在调用fetchFieldList的手传递了三个参数 obj、message、context,前者是一个对象,内部包含参数和token,中间是一个message组件,context是上线文,一般如何调用呢?

 

class App extends Component {
    state={
        loading:false
    }
    setLoading=(b)=>{
        this.setState({
            loading:b
        })
    }
    componentDidMount() {
        
        this.props.dispatch(loading(true));
        this.props.dispatch(fetchFieldList({
            token: this.props.user.data.token,
            gymId: this.props.user.data.gymId
        }, message, this));

    }

我们看到在App组件中的componentDidiMount组件中调用了dispatch,而其action就是一个函数执行,函数执行后返回一个action可执行函数。

但是props上面的user.data的属性哪里来的呢?

 

在APP组件的最下面:

const mapStateToProps = (state, ownProps) => { //拉取到新的信息  先走这个函数  再走componentWillReceiveProps

    if (state.fieldList.success) {
        let obj = JSON.parse(sessionStorage.getItem('state'))
        obj = Object.assign(obj, {fieldList: state.fieldList})
        //obj.user.data.gym=this.state.venueData.gym
        sessionStorage.setItem('state', JSON.stringify(obj))
        //
    }
    if (!state.user.data) {
        if (sessionStorage.getItem('state')) {
            state.user = JSON.parse(sessionStorage.getItem('state')).user
        }
    }

    return {
        user: state.user,
        fieldList: state.fieldList,
        loading: state.loading
    }
}

export default connect(mapStateToProps,)(App)

 

我们发现在组件的APP中我们先默认传递了一个参数,这些数据来自本地缓存,机sessionStorage,在mapstetetoprops

过程中,先更新类表数据,在获取用户数据,然后返回,这里的判断比较晦涩难懂,不知道什么意思。

 

总结:要添加一个一个sotre数据,需要三步

1、新建action

2、新建reducer action和reducer最好同名

3、将新建的reducer追加到index.js中的combineReducers函数。

 

这是store创建完成,但是还需要将store映射到需要使用的组件。

代码如上。

 

posted @ 2021-05-06 15:06  挥刀  阅读(223)  评论(0编辑  收藏  举报