Dva 中的异步处理
Dva 项目中默认使用 fetch 来发送网络请求。
项目中的 utils 目录中,封装了一个 request.js 文件,该文件中将 fetch 请求封装成了一个 request() 方法。我们发送请求时只需要引入该文件并调用 request() 方法就可以了。
在 Dva 的项目中,还自动创建了一个 services 目录,用来存放项目中所有请求 API 的文件。
例如我们现在需要发送一个“获取待办事项数据”的请求,就可以在 services 目录中创建一个 todoList.js 文件,然后在该文件中配置所有关于待办事项的请求 API。
import request from '../utils/request.js'
// 获取所有代办事项的数据
export const getTodosAsync = () => request('http://47.98.128.191:3000/todos/getTodos');
// 新增代办事项
export const addTodosAsync = (data) => request('http://47.98.128.191:3000/todos/addTodos', {
method: 'POST',
body: JSON.stringify(data)
});
组件中需要发送请求时,直接引入封装好的 API 文件,调用对应的方法即可:
import React, { useEffect } from 'react';
import { connect } from 'dva';
import { getTodosAsync } from '../services/todoList';
function TodoList({ todos, dispatch }) {
// 模拟组件挂载完成
useEffect(() => {
getTodos();
}, [])
const getTodos = async () => {
const res = await getTodosAsync();
console.log(res);
}
return (
// ...
);
}
// ...
Dva 项目中,如果要使用状态机来发送异步请求,整个大体的流程应该是:
组件调用状态机,状态机调用 API。
在 models 目录中的所有数据模块文件中,都有一个 effects 用来配置异步请求代码。
export default {
effects: {
*方法名({ payload }, { call, put }) {
const 请求结果 = yield call(异步请求方法名);
// 将结果保存到状态机中
yield put({ type: 'reducers 方法名', payload: 请求结果 })
}
}
}
例如,我们要在状态机中发送请求获取 TodoList 的所有数据:
import { getTodosAsync } from "../services/todoList";
export default {
// 命名空间
namespace: 'todoList',
state: {
todos: [],
},
// reducers 中用来设置修改 state 的方法:修改 state 的方式是需要返回一个新的对象
reducers: {
setTodos(state, action) {
return {
...state,
todos: action.payload
}
}
},
effects: {
*getTodosSaga({ payload }, { call, put }) {
// 状态机调 API
const { data } = yield call(getTodosAsync);
if (data.code) {
// 调用 reducers 中的方法,将数据传给 reducers
yield put({ type: 'setTodos', payload: data.data });
}
}
}
}
组件中通过 dispatch() 来调用状态机中的 saga 方法:
import React, { useEffect } from 'react';
import { getTodosAsync } from '../services/todoList';
function TodoList({ todos, dispatch }) {
// 模拟组件挂载完成
useEffect(() => {
getTodos();
}, [])
const getTodos = async () => {
// 调用状态机的方法
dispatch({type: 'todoList/getTodosSaga'})
}
return (
// ...
);
}