上节课我们完成了用很精简的方式来完成了redux
版的求和案例,但是上节课那是精简版的,省略了创建动作对象那一步,而且整个过程也没有严格地遵守规范,那么这节课我们来完整地用redux
来实现我们之前的哪个案例。
回顾
在我们开始这节课的内容之前,我们先对上节课的内容来做一个简单的回顾。
subscribe API
来监测redux
中的state
getState API
来获取redux
中的state
createStore
来创建store
reducer
本质上是一个函数,接收之前的状态和动作对象redux
中不关心其他的东西,制作基础操作redux
中的state
改变不重新调render
以上便是上节课的主要要点,接下来我们来开始这节课的学习。
Action Creator
我们之前精简版来使用redux
的时候是不是直接手写的动作对象啊?但是呢样的话不符合redux
的使用规范,正常的流程是什么样子的呢?我们是需要由组件发起,然后由Action Creators
来创建一个动作对象,然后再通过dispatch
分发出去的。那么我们现在既然要用到Action Creators
了,我们是不是要创建一个文件来专门为我们创建动作对象啊?
而且我们看见了这个Action Creators
也是复数,那么是不是和Reducers
一样?每个组件要有一个对应的Action Creator
,所以说我们就要在redux
文件夹下创建一个sum_action_creator.js
文件。我们这里说一下,因为redux
也不是组件,所以说要在src
下创建一个文件夹专门用于存放redux
相关的文件。
那么现在我们文件创建好了,依然还是之前那样,我们不知道如何来创建一个动作对象啊。而且这个creator
的本质上又是什么呢?我们来想一想,我们这个creator
是用来干什么的?是不是专门为Sum
组件创建动作对象的?那么我们的Sum
组件都有哪些动作?是不是加和减?那么我们这里的creator
只要创建了动作对象之后是不是要交出去给dispatch
?那么是不是就意味着要返回一个对象给dispatch
做参数啊?那么直接用函数就可以完成了啊。
export const createIncrementAction = data => ({ type: 'increment', data }); export const createDecrementAction = data => ({ type: 'decrement', data });
大家来看代码,这是什么意思?我们是不是分别暴露了两个函数,这两个函数都是箭头函数,箭头函数都接收一个参数就是我们要操作的对象,然后我们返回一个对象,这个对象就是我们的动作对象,有人可能说这两个函数长得这么像,我们给写成一个函数吧,当然可以,但是我们先这么写,我们一步一步来,我们这个案例会一步一步地进行版本迭代,到了最后一个版本我们会给大家呈现出一个最规范的版本。现在就先这么写,不要给自己太大的压力,先把族简单的原理搞懂。
那么我们再来问大家,我这个箭头函数问什么要用小括号?我们是不是要返回一个对象?对象是不是以花括号来作为边界的?而函数体是不是也是以花括号作为边界的?如果我们这里不用小括号把对象括起来的话,箭头函数就默认你这不是对象,而是函数体。
创建动作对象
现在我们已经写好了我们的Action Creator
了,那么我们怎么用?首先这个Action Creator
是由谁触发的?是不是我们的组件触发这里的Creator
来创建动作对象的?那么我们回到组件中来:
看看我们这是在干什么啊?我们是不是自己手写了一个动作对象交给了dispatch
啊?现在呢我们既然已经准备好了Creator
那么我们还要这么写吗?我们是不是直接调用我们的Creator
来创建动作对象然后再交给dispatch
就行了?
import React, { Component } from 'react' import store from '../../redux/store'; import { createIncrementAction, createDecrementAction } from '../../redux/sum_action_creator'; export default class Sum extends Component { componentDidMount() { store.subscribe(() => this.setState({})); } render() {...} add = () => { const { value } = this.selectNum; store.dispatch(createIncrementAction(value * 1)); } dec = () => { const { value } = this.selectNum; store.dispatch(createDecrementAction(value * 1)); } odd = () => { const { value } = this.selectNum; if (store.getState() % 2 !== 0) store.dispatch(createIncrementAction(value * 1)); } async = () => { const { value } = this.selectNum; setTimeout(() => { store.dispatch(createIncrementAction(value * 1)); }, 1000) } }
我们来看代码,首先这些函数是不是都在sum_action_creator.js
里啊?那么我们就得先导入,然后再之前手写动作对象的地方直接调用函数。这样的话我们就可以通过我们的Action Creator
来创建我们的动作对象了。那么我们再来看一下效果吧
我们来看一下,这次我们是不是也可以完成我们想要的效果。
常量模块
可能大家以为我们到上面那一步我们的完整版就写完了,但是我们有一个问题,当然并不是代码上的问题,我们来想一下,我们的reducer
里面匹配动作的type
以及我们创建动作对象里面的type
是不是都是我们手写的?那么如果不小心单词写错了怎么办?那我们不就匹配不上了嘛。所以说我们要添加一个常来那个模块在redux
下创建一个constant.js
文件
// constant.js export const INCREMENT = "increment"; export const DECREMENT = "decrement"; // sum_action_creator.js import { INCREMENT, DECREMENT } from "./constant" export const createIncrementAction = data => ({ type: INCREMENT, data }); export const createDecrementAction = data => ({ type: DECREMENT, data }); // sum_reducer.js import { INCREMENT, DECREMENT } from './constant'; export default function sumReducer(preState, action) { if (preState === undefined) preState = 0; const { type, data } = action; switch (type) { case INCREMENT: return preState + data; case DECREMENT: return preState - data; default: return preState; } }
我们来看代码,我们在constant.js
里面定义了两个常量,然后分别暴露出来,然后再用到的地方直接导入常量,这样我们就不会因为单词不小心写错导致功能不起作用了。
总结
Action Creators
本质上其实也是函数- 我们通过常量模块来定义动作类型,防止单词写错
Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.
Link of this article:https://work.lynchow.com/article/demo_react_redux_full/