003-and design-dva.js 知识导图-01-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

原文地址:https://www.cnblogs.com/bjlhx/p/9213862.html

时间: 2024-10-29 21:05:56

003-and design-dva.js 知识导图-01-Reducer,Effect,Subscription,Router,dva配置,工具的相关文章

002-and design-dva.js 知识导图-01JavaScript 语言,React Component

一.概述 参看:https://github.com/dvajs/dva-knowledgemap react 或 dva 时会不会有这样的疑惑: es6 特性那么多,我需要全部学会吗? react component 有 3 种写法,我需要全部学会吗? reducer 的增删改应该怎么写? 怎么做全局/局部的错误处理? 怎么发异步请求? 怎么处理复杂的异步业务逻辑? 怎么配置路由? 二.JavaScript 语言 2.1.变量声明 const 和 let 不要用 var,而是用 const 和

编程随笔-ElasticSearch知识导图(1):全景

1. 由ElasticSearch开始的思考 ??官方介绍Elasticsearch(以下简称ES)是一个基于Apache Lucene(TM)的开源搜索引擎.但我最初了解ES却是从NoSQL数据库开始,在使用.研究了ES一段时间后,我发现这是一个优秀的分布式部署软件,不仅是一个全文搜索引擎.还是一个分布式存储系统.一个分布式数据库.??在ES之前我们习惯使用关系数据库(RDBMS)来进行现实数据世界的建模,将现实世界中的领域模式表示为实体-关系模型(E-R模型).但现实世界的领域本体(Onto

编程随笔-ElasticSearch知识导图(2):分布式架构

1. 集群结构 ??在我们探究ES的分布式架构之前,我们使用一个简单的导图描述一下我们在设计分布式系统时会考虑的问题,如图1所示.??带着图1中的问题我们来探究一下ES集群,ES集群是一个典型的主从结构,从某种意义上来说,符合现今大多数主流分布式存储.分布式计算系统的审美要求.下面我们逐步来了解集群中的这些东东.??先用来自文献2的一张集群结构图开始我们的探究. 1.1 集群节点 ??在ES集群中,一个ES实例就是一个节点(node),图2中显示的是三个节点的一个集群.集群中有一个主节点(mas

思维导图学习法之MindManager软件管理附件工具

MindManager15中文版是一款应用性软件,添加附件可对导图进行进一步的解释,管理附件是对添加到思维导图的附件进行管理的工具,可以对附件进行打开.另存为.添加.重命名.删除的操作,本教程主讲如何使用MindManager15中文版中的管理附件工具. 打开MindManager15中文版思维导图软件,新建导图,添加附件,制作后的思维导图如图所示: 管理附件的具体操作如下: 点击需要管理的主题,点击附件下面的倒置三角,选择管理附件.或者思维导图中回形针状的附件图标,选择管理附件;快捷键操作:C

js思维导图

思维导图分享以及MindManager使用说明

来源于: http://www.cnblogs.com/muhongxing/archive/2009/12/22/1628782.html http://www.cnblogs.com/muhongxing/archive/2009/12/29/1635104.html 我使用思维导图已经有一段时间了,也有了一些自己的经验,甚至,在工作和生活中,思维导图已经是我必不可少的一项工具.当智哥问我能不能用一句话解释清楚思维导图的时候,我迟疑了一下,还是没法说清楚(看来要将<金字塔原理>列入读书计划

如此之好,大家都在用-----思维导图mindmanager

思维导图mindmanager可用于不同领域,如文化.教育.科技.商业.金融.工业.行政等,可以在决策分析.沟通管理.营销管理.财务管理.时间管理等方面应用,以提高工作的效率. 文化:家喻户晓的小说<哈里?波特>,其作者罗琳便是用思维导图演绎出小说中丰富多彩的情节和人物. 教育:思维导图mindmanager帮助师生掌握正确有效的学习方法,建立系统的知识框架体系,促进师生间的交流沟通,实现因材施教,使整个教学过程和流程设计更加系统.科学有效,促进教学的效率和质量的提高.促进学生之间的交流与合作

程序员如何用思维导图高效学习Java编程

Java作为一种常见的计算机编程语言,它具有简单.稳定.多线等特点,被广泛运用于PC.游戏控制台.数据中心.超级计算机以及互联网,相对于C++,Java会稍微容易些,但是依然需要我们学会很多的编程,作为一名程序员,如何系统的掌握这些程序呢?下面是分享的用思维导图学习Java编程方法介绍,一起看看吧! 为什么要用思维导图学习Java呢? 首先思维导图是一种结构性模型,有利于整合知识框架,其次,思维导图是一种带色彩的图文结合,相对于单纯的文字而言,更好的被人们所记住,迅捷画图作为一款好用的思维导图工

如何正确绘制思维导图

与传统的书写方式不同,思维导图是以图形的方式表达信息的.虽然思维导图中也会有字,而且是很多字,但这些字都是依附于图形的,图形在思维导图中发挥着至关重要的作用.今天的??思维导图教程??就讲解了我们在绘制导图是该注重的技巧. 理解图形的作用并积极使用图形是思维导图应用过程中的一个主要障碍.我们大多数人在日常生活中很少画图,却经常写字.一开始在导图中大量使用文字会让学习者感到很舒服,因为这并没有远离他们的旧习惯.但是,当他们需要用思维导图实实在在地提高成绩的时候,问题就出现了,他们发现思维导图提高记