真实世界的 ReactJS 和 Redux(第 2 部分)

这是关于真实世界 ReactJS 使用以及我们在 Threat Stack 扩展我们的应用程序所学到的一系列博客文章中的第二篇。


这是关于真实世界ReactJS 使用以及我们在Threat Stack中了解如何扩展我们的应用程序的一系列博客文章中的第二篇。

在这篇文章中,我们将展示基于第 1 部分中所示的 api 中间件的操作。

让每个人都在同一页面上

当涉及到正在创建的产品和应用程序的类型时,确保所有团队成员始终处于同一页面上至关重要。ReactJS 需要一定的学习曲线,但一旦人们有时间弄清楚它,就可以克服它。

公平地说,学习一个全新的系统并不总是世界上最容易的事情,但是很多人已经学会了如何让 ReactJS为他们工作,我们想要认识这些人并使其非常清楚这是可以完成的事情。

无论如何,每个人都应该想了解 ReactJS,因为它可能很快就会成为他们生活中更重要的一部分。

在这篇文章中,我们将展示基于第 1 部分中所示的 api 中间件的操作。

仍然确保回答这些问题:

  • 开发的难易程度如何?
  • 新团队成员能以多快的速度了解正在发生的事情?
  • 您能以多快的速度找出损坏的地方?

有时会出现一个看似简单的功能请求,如下所示:

如果 X 发生了 Y,但前提是状态看起来像 Z。

由于您希望保持代码在 react(视图)和 redux(数据管理)之间解耦,因此像这样的简单请求最终看起来比应有的更困难。

一个很好的例子是 客户端跟踪。

在某些时候,您会想要,不,需要跟踪用户何时单击某物并传递显示中有多少项目或有关当前状态的其他信息。

第一步是 分析中间件。

事情是基于一个恰当地命名为“分析”的属性。

所以动作看起来像这样:

return {  types: [ MARK_READ, MARK_READ_SUCCESS, MARK_READ_ERROR ],  callAPI: () => Api.updateTodos({    ids,    isRead: true   }),  analytics: {    [MARK_READ_SUCCESS] : {      idsCount: ids.length,      isSuccess: true    },    [MARK_READ_ERROR] : {      idsCount: ids.length,      isSuccess: false    }  }}


到目前为止……并不可怕。

根据事件类型(成功/错误),我们可以跟踪不同的事情。

但是一个新的要求进来了…… 你不会相信接下来发生的事情。

如果成功,我们还需要将用户重定向到不同的部分。

return {  types: [ MARK_READ, MARK_READ_SUCCESS, MARK_READ_ERROR ],  callAPI: () => Api.updateTodos({    ids,    isRead: true   }),  analytics: {    [MARK_READ_SUCCESS] : {      idsCount: ids.length,      isSuccess: true    },    [MARK_READ_ERROR] : {      idsCount: ids.length,      isSuccess: false    }  },  redirect: ({ state }) {  }}


我们制作了另一个寻找特定属性的中间件。

我们确实做到了。

但这不会扩展。

我们需要更通用的东西,可以针对不同的用例进行扩展。

一个超级好用的通用中间件

设想:

if I'm filtering a list of todos    If I mark all as read         clear the filter     If I mark only some of them as read      leave the filter onOnError show an error notification

规则:

  • 这种逻辑不应该存在于视图中。
  • 这是基于标记待办事项的动作。
    如果我添加此组件的不同版本,例如 A/B 测试,则状态应该会更新,并且一切都应该正常工作。

component.react.js

handleMarkRead (ids) {    dispatch(markReadTodos(ids));}

action.js

import { clearTodosFilter } from '../filterActions';import {    MARK_READ,    MARK_READ_SUCCESS,    MARK_READ_ERROR} from '../constants'export function updateItem (ids) {  return {    types: [ MARK_READ, MARK_READ_SUCCESS, MARK_READ_ERROR ],    callAPI: () => Api.updateTodos({        ids,        isRead: true     }),    effect ({ dispatch, state, type }) {      if (type === MARK_READ_ERROR) {        dispatch(showErrNotification(         'There was an error updating your todos'         ));        }      if (type === MARK_READ_SUCCESS) {        const { todosById } = this.state;        let hasReadAll = true;        for ( const id in todosById) {          if (!todosById[id].isRead) {            hasReadAll = false;            break;          }        }        if (hasReadAll) {          dispatch(clearTodosFilter());        }      }    },  };}

设想:

当用户更新项目时,如果失败则显示错误通知。

如果成功,则显示不同的通知,但前提是项目为 FOO 或其他状态已更改。

.

item.react.js

handleUpdateItem (item) {  dispatch(updateItem({     item  });}


ItemActions.js

  1. 将发生更新项目调用。
  2. 应用程序State将被更新。
  3. 如果出现错误:
    – 我们将发送错误通知。
  4. 如果它成功并且当前更改计数(基于当前状态)无效,我们将发送不同的通知。
import { showErrNotifcation } from '../notificationActions';import {    UPDATE_ITEM,    UPDATE_ITEM_SUCCESS,    UPDATE_ITEM_ERROR,    MAX_CHANGES} from '../constants'export function updateItem ({ item, prevItem }) {  return {    types: [ UPDATE_ITEM, UPDATE_ITEM_SUCCESS, UPDATE_ITEM_ERROR ],    callAPI: () => Api.updateItem(item),    effect ({ dispatch, state, type }) {      if (type === UPDATE_ITEM_ERROR) {        dispatch(showErrNotification('Error updating item'));        }      if (type === UPDATE_ITEM_SUCCESS) {        const { itemsById } = this.state;        if (itemsById[item.id].changes === MAX_CHANGES) {          dispatch(showNotification(            `You can no longer alter this item`           ));         }      }    },  };}

而中间件...

effectsMiddleware.js

export default function effectsMiddleware ({ dispatch, getState }) {  return next => action => {    const nextValue = next(action);    if (!action.effect) {      if (!isFunction(action.effect)) {        throw new Error('Expected effect to be a function');      }      action.effect({        dispatch : dispatch,        state    : getState(),        type     : action.type,      });      delete action.effect;    }    return nextValue;  };}



但是,您需要确保将其放置在您的其他自定义中间件之后。

const middleware = process.env.NODE_ENV === 'production' ?  [ thunk,  callAPIMiddleware, effectsMiddleware ] :  [ thunk, callAPIMiddleware, effectsMiddleware, logger() ];


我们结束的地方。..

  • 子动作的逻辑是动作代码。
  • 由于我们是dispatching其他子操作,您可以使用 grep 获取操作名称,它们将显示在您的控制台上进行调试。
  • 您将能够遵循控制台中代码中发生的操作的流程。



发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章