![](https://oss.jqhtml.com/wp-content/uploads/2020/7/nuUfqu.jpeg)
欢迎继续阅读《Taro 小程序开发大型实战》系列,前情回顾:
- 熟悉的 React,熟悉的 Hooks:我们用 React 和 Hooks 实现了一个非常简单的添加帖子的原型
- 多页面跳转和 Taro UI 组件库:我们用 Taro 自带的路由功能实现了多页面跳转,并用 Taro UI 组件库升级了应用界面
- 实现微信和支付宝多端登录:实现了微信、支付宝以及普通登录和退出登录
- 使用 Hooks 版的 Redux 实现大型应用状态管理(上篇):使用 Hooks 版的 Redux 实现了
user
逻辑的状态管理重构 - 使用 Hooks 版的 Redux 实现大型应用状态管理(下篇):使用 Hooks 版的 Redux 实现了
post
逻辑的状态管理重构 - Taro 小程序开发大型实战(六):尝鲜微信小程序云(上篇):
user
逻辑接入微信小程序云
在上一篇文章中,我们将我们两大逻辑之一 User 部分接入了 Redux 异步处理流程,接着接入了微信小程序云,使得 User 逻辑可以在云端永久保存,好不自在:),两兄弟一个得了好处,另外一个不能干瞪眼对吧?在这一篇教程中,我们想办法把 User 另外一个兄弟 Post 捞上来,也把 Redux 异步流程和微信小程序给它整上,这样就齐活了。
我们首先来看一看最终的完成效果:
![](https://oss.jqhtml.com/wp-content/uploads/2020/7/fqa2Mn.gif)
如果你不熟悉 Redux,推荐阅读我们的《Redux 包教包会》系列教程:
如果你希望直接从这一步开始,请运行以下命令:
git clone -b miniprogram-start https://github.com/tuture-dev/ultra-club.git
cd ultra-club
本文所涉及的源代码都放在了Github 上,如果您觉得我们写得还不错,希望您能给️这篇文章点赞+Github仓库加星️哦~
此教程属于 React 前端工程师学习路线的一部分,欢迎来 Star 一波,鼓励我们继续创作出更好的教程,持续更新中~
“六脉神剑” 搞定 createPost 异步逻辑
不知道看到这里的读者有没有发现上篇文章其实打造了一套讲解模式,即按照如下的 “六步流程” 来讲解,我们也称为 “六脉神剑” 讲解法:
- 将组件中的同步逻辑重构到异步逻辑
- 声明和补充对应需要的异步
sagas
文件 - 定义
sagas
需要的常量文件 - 定义
sagas
涉及到的前端 API 文件 - 创建对于的微信小程序云函数,并编写对应的 Node.js 处理逻辑
- 定义对应的
reducers
文件 - 如此往复
可以看到我们上面的讲解顺序实际上是按照前端数据流的流动来进行的,我们对标上面的讲解逻辑来看一下前端数据流是如何流动的:
- 从组件中通过对应的常量发起异步请求
-
sagas
监听到对应的异步请求,开始处理流程 - 在
sagas
调用对应的前端 API 文件向微信小程序云发起请求 - 微信小程序云函数处理对应的 API 请求,返回数据
-
sagas
中获取到对应的数据,dispatch
action 到对应的reducers
处理逻辑 -
reducers
接收数据,开始更新本地 Redux Store 中的state
- 组件中重新渲染
好的,了解了讲解逻辑和对应前端数据流动逻辑之后,我们马上来实践这套逻辑,把 User 逻辑的好兄弟 Post 逻辑搞定。
第一剑:PostForm
组件中发起异步请求
首先从创建帖子逻辑动刀子,我们将创建帖子接入异步逻辑并接通小程序云,让文章上云。打开 src/components/PostForm/index.jsx
,对其中的内容作出对应的修改如下:
import { useDispatch, useSelector } from '@tarojs/redux'
import './index.scss'
import { CREATE_POST } from '../../constants'
export default function PostForm() {
const [formTitle, setFormTitle] = useState('')
const [formContent, setFormContent] = useState('')
const userId = useSelector(state => state.user.userId)
const dispatch = useDispatch()
... }
dispatch({
type: CREATE_POST,
payload: {
postData: {
title: formTitle,
content: formContent,
},
userId,
},
})
setFormTitle('')
setFormContent('')
}
return (
可以看到,上面的内容做了如下四处修改:
- 首先我们现在是接收用户的文章输入数据然后向小程序云发起创建文章的请求,所以我们将之前的
dispatch
SET_POSTS Action 改为 CREATE_POST Action,并且将之前的 action payload 简化为postData
和userId
,因为我们可以通过小程序云数据库查询userId
得到创建文章的用户信息,所以不需要再携带用户的数据。 - 接着,因为我们不再需要用户的
avatar
和nickName
数据,所以我们删掉了对应的useSelector
语句。 - 接着,因为请求是异步的,所以需要等待请求完成之后再设置对应的发表文章的状态以及发表文章弹出层状态,所以我们删掉了对应的
dispatch
SET_POST_FORM_IS_OPENED Action 逻辑以及Taro.atMessage
逻辑。 - 最后我们删掉不需要的常量
SET_POSTS
和SET_POST_FORM_IS_OPENED
,然后导入异步创建文章的常量CREATE_POST
。
增加 Action 常量
我们在上一步中使用到了 CREATE_POST
常量,打开 src/constants/post.js
,在其中增加 CREATE_POST
常量:
export const CREATE_POST = 'CREATE_POST'
到这里,我们的 “六步流程” 讲解法就走完了第一步,即从组件中发起对应的异步请求,这里我们是发出的 action.type
为 CREATE_POST
的异步请求。
第二剑: 声明和补充对应需要的异步 sagas
文件
在 “第一剑” 中,我们从组件中 dispatch 了 action.type 为 CREATE_POST
的异步 Action,接下来我们要做的就是在对应的 sagas
文件中补齐响应这个异步 action 的 sagas。
在 src/sagas/
文件夹下面创建 post.js
文件,并在其中编写如下创建文章的逻辑:
import Taro from '@tarojs/taro'
import { call, put, take, fork } from 'redux-saga/effects'
import { postApi } from '../api'
import {
CREATE_POST,
POST_SUCCESS,
POST_ERROR,
SET_POSTS,
SET_POST_FORM_IS_OPENED,
} from '../constants'
function* createPost(postData, userId) {
try {
const post = yield call(postApi.createPost, postData, userId)
// 其实以下三步可以合成一步,但是这里为了讲解清晰,将它们拆分成独立的单元
// 发起发帖成功的 action
yield put({ type: POST_SUCCESS })
// 关闭发帖框弹出层
yield put({ type: SET_POST_FORM_IS_OPENED, payload: { isOpened: false } })
// 更新 Redux store 数据
yield put({
type: SET_POSTS,
payload: {
posts: [post],
},
})
// 提示发帖成功
Taro.atMessage({
message: '发表文章成功',
type: 'success',
})
} catch (err) {
console.log('createPost ERR: ', err)
// 发帖失败,发起失败的 action
yield put({ type: POST_ERROR })
// 提示发帖失败
Taro.atMessage({
message: '发表文章失败',
type: 'error',
})
}
}
function* watchCreatePost() {
while (true) {
const { payload } = yield take(CREATE_POST)
console.log('payload', payload)
yield fork(createPost, payload.postData, payload.userId)
}
}
export { watchCreatePost }
可以看到,上面的改动主要是创建 watcherSaga
和 handlerSaga
。
创建 watcherSaga
- 我们创建了登录的
watcherSaga
:watchCreatePost
,它用来监听action.type
为CREATE_POST
的 action,并且当监听到CREATE_POST
action 之后,从这个 action 中获取必要的postData
和userId
数据,然后激活handlerSaga
:createPost
去处理对应的创建帖子的逻辑。 - 这里的
watcherSaga
:watchCreatePost
是一个生成器函数,它内部是一个while
无限循环,表示在内部持续监听CREATE_POST
action。 - 在循环内部,我们使用了
redux-saga
提供的effects helper
函数:take
&