003-and design-dva.js 知识导图-02-Reducer,Effect,Subscription,Router,dva配置,工具
一、Reducer
reducer 是一个函数,接受 state 和 action,返回老的或新的 state 。即:(state, action) => state
增删改
以 todos 为例。
app.model({
namespace: 'todos',
state: [],
reducers: {
add(state, { payload: todo }) {
return state.concat(todo);
},
remove(state, { payload: id }) {
return state.filter(todo => todo.id !== id);
},
update(state, { payload: updatedTodo }) {
return state.map(todo => {
if (todo.id === updatedTodo.id) {
return { ...todo, ...updatedTodo };
} else {
return todo;
}
});
},
},
};
嵌套数据的增删改
建议最多一层嵌套,以保持 state 的扁平化,深层嵌套会让 reducer 很难写和难以维护。
app.model({
namespace: 'app',
state: {
todos: [],
loading: false,
},
reducers: {
add(state, { payload: todo }) {
const todos = state.todos.concat(todo);
return { ...state, todos };
},
},
});
下面是深层嵌套的例子,应尽量避免。
app.model({
namespace: 'app',
state: {
a: {
b: {
todos: [],
loading: false,
},
},
},
reducers: {
add(state, { payload: todo }) {
const todos = state.a.b.todos.concat(todo);
const b = { ...state.a.b, todos };
const a = { ...state.a, b };
return { ...state, a };
},
},
});
二、Effect
示例:
app.model({
namespace: 'todos',
effects: {
*addRemote({ payload: todo }, { put, call }) {
yield call(addTodo, todo);
yield put({ type: 'add', payload: todo });
},
},
});
Effects
put
用于触发 action 。
yield put({ type: 'todos/add', payload: 'Learn Dva' });
call
用于调用异步逻辑,支持 promise 。
const result = yield call(fetch, '/todos');
select
用于从 state 里获取数据。
const todos = yield select(state => state.todos);
错误处理
全局错误处理
dva 里,effects 和 subscriptions 的抛错全部会走 onError hook,所以可以在 onError 里统一处理错误。
const app = dva({
onError(e, dispatch) {
console.log(e.message);
},
});
然后 effects 里的抛错和 reject 的 promise 就都会被捕获到了。
本地错误处理
如果需要对某些 effects 的错误进行特殊处理,需要在 effect 内部加 try catch 。
app.model({
effects: {
*addRemote() {
try {
// Your Code Here
} catch(e) {
console.log(e.message);
}
},
},
});
异步请求
异步请求基于 whatwg-fetch,API 详见:https://github.com/github/fetch
GET 和 POST
import request from '../util/request'; // GET
request('/api/todos'); // POST
request('/api/todos', {
method: 'POST',
body: JSON.stringify({ a: 1 }),
});
统一错误处理
假如约定后台返回以下格式时,做统一的错误处理。
{
status: 'error',
message: '',
}
编辑 utils/request.js,加入以下中间件:
function parseErrorMessage({ data }) {
const { status, message } = data;
if (status === 'error') {
throw new Error(message);
}
return { data };
}
然后,这类错误就会走到 onError hook 里。
三、Subscription
subscriptions 是订阅,用于订阅一个数据源,然后根据需要 dispatch 相应的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。格式为 ({ dispatch, history }) => unsubscribe 。
异步数据初始化
比如:当用户进入 /users 页面时,触发 action users/fetch 加载用户数据。
app.model({
subscriptions: {
setup({ dispatch, history }) {
history.listen(({ pathname }) => {
if (pathname === '/users') {
dispatch({
type: 'users/fetch',
});
}
});
},
},
});
path-to-regexp Package
如果 url 规则比较复杂,比如 /users/:userId/search,那么匹配和 userId 的获取都会比较麻烦。这是推荐用 path-to-regexp 简化这部分逻辑。
import pathToRegexp from 'path-to-regexp'; // in subscription
const match = pathToRegexp('/users/:userId/search').exec(pathname);
if (match) {
const userId = match[1];
// dispatch action with userId
}
四、router
Config with JSX Element (router.js)
<Route path="/" component={App}>
<Route path="accounts" component={Accounts}/>
<Route path="statements" component={Statements}/>
</Route>
详见:react-router
Route Components
Route Components 是指 ./src/routes/ 目录下的文件,他们是 ./src/router.js 里匹配的 Component。
通过 connect 绑定数据
比如:
import { connect } from 'dva';
function App() {}
function mapStateToProps(state, ownProps) {
return {
users: state.users,
};
}
export default connect(mapStateToProps)(App);
然后在 App 里就有了 dispatch 和 users 两个属性。
Injected Props (e.g. location)
Route Component 会有额外的 props 用以获取路由信息。
- location
- params
- children
更多详见:react-router
基于 action 进行页面跳转
import { routerRedux } from 'dva/router';
// Inside Effects
yield put(routerRedux.push('/logout'));
// Outside Effects
dispatch(routerRedux.push('/logout'));
// With query
routerRedux.push({
pathname: '/logout',
query: {
page: 2,
},
});
除 push(location) 外还有更多方法,详见 react-router-redux
五、dva配置
Redux Middleware
比如要添加 redux-logger 中间件:
import createLogger from 'redux-logger';
const app = dva({
onAction: createLogger(),
});
注:onAction 支持数组,可同时传入多个中间件。
history
切换 history 为 browserHistory
import { browserHistory } from 'dva/router';
const app = dva({
history: browserHistory,
});
去除 hashHistory 下的 _k 查询参数
import { useRouterHistory } from 'dva/router';
import { createHashHistory } from 'history';
const app = dva({
history: useRouterHistory(createHashHistory)({ queryKey: false }),
});
六、工具
通过 dva-cli 创建项目
先安装 dva-cli 。
$ npm install dva-cli -g
然后创建项目。
$ dva new myapp
最后,进入目录并启动。
$ cd myapp
$ npm start
003-and design-dva.js 知识导图-02-Reducer,Effect,Subscription,Router,dva配置,工具的更多相关文章
- 002-and design-dva.js 知识导图-01JavaScript 语言,React Component
一.概述 参看:https://github.com/dvajs/dva-knowledgemap react 或 dva 时会不会有这样的疑惑: es6 特性那么多,我需要全部学会吗? react ...
- JS思维导图(转)
思维导图不得不说是学习及温习的极佳方法,这里转载一波网上他人的精品JS思维导图十张,共同学习,如有冒犯原著可联系本人及时处理.
- 【琉忆分享】新手如何学习PHP?附上PHP知识导图。
你好,是我--琉忆.PHP程序员面试系列图书作者. 作为一名PHP开发者过来人,也是经历了菜鸟到老手的过程,在此给那些想学PHP的同学指条路,即使你是转行学PHP一样可以学会PHP. (如果觉得下面这 ...
- Angular.js思维导图
AngularJS的四大特性的思维导图如下: 将AngularJS应用于工作:其思维导图如下: AngularJS服务思维导图:
- 前端-Node.js思维导图笔记
看不清的朋友右键保存或者新窗口打开哦!喜欢我可以关注我,还有更多前端思维导图笔记
- 前端-JS思维导图
看不清的朋友右键保存或者新窗口打开哦!喜欢我可以关注我,还有更多前端思维导图笔记
- JS思维导图
- js知识框架图
- dva.js 上手
来源:https://pengtikui.cn/dva.js-get-started/ ——------------------------------------------------------ ...
随机推荐
- React封装RadioGroup
class RadioGroup extends React.Component { getRadioComponent(item, index) { return <div className ...
- Hbase学习之javaApI封装
http://qindongliang.iteye.com/blog/2096140
- 彩色图像的直方图均衡化matlab代码
彩色图像的直方图均衡化 - YangYudong2014的专栏 - CSDN博客 http://blog.csdn.net/yangyudong2014/article/details/4051503 ...
- [转]ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)
在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie ...
- shell基础篇(三)--引号
---今天篇幅比较少:只介绍引号. shell中的引号有三种:双引号",单引号',反引号`1. 双引号:由双引号括起来的字符,除$.倒引号(`)和反斜线(\)仍保留其特殊功能外,其余字符均作 ...
- 如果程序太大而不能在DOS下运行,怎样才能使它在DOS下运行呢?
如果你的程序因太大(超过640KB)而无法在DOS下运行,有两种办法可为该程序提供更多的内存.一种办法是使用覆盖管理程序(overlay manager).覆盖管理程序用来管理程序的模块,并根据需要把 ...
- 格式化输出%s和%S的区别
使用s时,printf是针对单字节字符的字符串,而wprintf是针对宽字符的 使用S时,正好相反,printf针对宽字符 CString中的format与printf类似,在unicode字符集的工 ...
- 《C++ Primer Plus》第12章 类和动态内存分配 学习笔记
本章介绍了定义和使用类的许多重要方面.其中的一些方面是非常微妙甚至很难理解的概念.如果其中的某些概念对于您来说过于复杂,也不用害怕——这些问题对于大多数C++的初学者来说都是很难的.通常,对于诸如复制 ...
- Apktool源码解析——第一篇
著名的apktool是android逆向界用的最普遍的一个工具,这个项目的原始地址在这里http://code.google.com/p/android-apktool/,但是你们都懂的在天朝谷歌是无 ...
- devstack screen 详解
n my previous blog i discussed how to install devstack based openstack. Now if I need to restart ind ...