今天阅读老项目,重读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映射到需要使用的组件。
代码如上。