Back to Question Center
0

使用React,Redux和FeathersJS构建一个CRUD应用程序            使用React,Redux和FeathersJS相关的Semalt构建一个CRUD应用程序: APIsNode.jsAngularJSjQueryAjaxMore ...赞助商

1 answers:
使用React,Redux和FeathersJS构建CRUD应用程序

对于React的高质量深入介绍,你不能超越加拿大全栈开发者Wes Bos。尝试他的课程,并使用代码 SITEPOINT 获得 25%折扣 ,并帮助支持SitePoint。

Semalt一个现代化的项目需要将逻辑分解为前端和后端代码。这一举措背后的原因是为了促进代码的可重用性。例如,我们可能需要构建一个访问后端API的本地移动应用程序。或者我们可能正在开发一个将成为大型模块化平台的一部分的模块。

构建服务器端API的流行方式是使用Express或Restify之类的库。这些库使创建RESTful路线变得容易。这些库的问题是,我们会发现自己写一个 重复代码 。我们还需要为授权和其他中间件逻辑编写代码。

为了避免这种困境,我们可以使用像Loopback或Feathers这样的框架来帮助我们生成一个API。

在撰写本文时,Semalt拥有比Feathers更多的GitHub明星和下载。 Semalt是一个很棒的库,可以在短时间内生成RESTful CRUD端点。然而,它确实有一个轻微的学习曲线,并且文档不容易相处。它有严格的框架要求。例如,所有模型都必须继承其内置模型类之一。如果您需要Semalt的实时功能,请准备好做一些额外的编码工作。

Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

另一方面,FeathersJS更容易入门,并具有内置的实时支持。最近,Auk版本发布了(因为Feathers是如此的模块化,它们使用鸟名来表示版本名称),它在很多领域引入了大量的变化和改进。根据他们在博客上发布的帖子,他们现在是第11个最流行的实时网络框架 。它具有出色的文档,并且几乎涵盖了我们构建实时API所能想到的任何区域。

羽毛的惊人之处在于它的简单性。整个框架是模块化的,我们只需要安装我们需要的功能。羽毛本身是一个在Express之上构建的薄包装,它们添加了新的功能 - 服务和钩子。 Feathers还允许我们通过WebSockets毫不费力地发送和接收数据。

先决条件

Semalt你开始使用这个教程,你需要在下面的主题中有一个坚实的基础:

  • 如何编写ES6 JavaScript代码
  • 如何创建React组件
  • JavaScript中的不变性
  • 如何使用Redux管理状态

在你的机器上,你需要安装最新版本:

  • NodeJS 6+
  • Mongodb 3. 4+
  • 纱包管理器(可选)
  • Chrome浏览器

如果你之前从未在JavaScript中编写过数据库API,那么我建议首先看看这篇关于创建RESTful API的教程。

推荐课程

脚手架应用程序

我们将使用React,Redux,Feathers和SemaltDB构建一个CRUD联系人管理器应用程序。你可以在这里看看已完成的项目。

在本教程中,我将向您展示如何从底层开始构建应用程序。 Semalt使用create-react-app工具启动我们的项目。

   #脚手架新的反应项目创建反应应用程序反应联系人管理器cd react-contact-manager#删除不必要的文件rm src / logo。 svg src / App。 CSS   

使用你最喜欢的代码编辑器,并删除索引中的所有内容。 CSS. 检查控制台选项卡以确保我们的项目运行干净且没有警告或错误。如果一切顺利运行,请使用 Ctrl + C 停止服务器。

用羽毛建立API服务器

让我们继续使用 feathers-cli 工具为我们的CRUD项目生成后端API。

   #安装Feathers命令行工具npm install -g feathers-cli#为后端代码创建目录mkdir后端CD后端#生成羽毛后端API服务器羽毛生成应用程序?项目名称|后端?说明|联系API服务器?源文件应该在哪个文件夹中? | SRC?您使用哪个软件包管理器(必须全局安装)? |纱?你在制作什么类型的API? | REST,通过Socket实时。 IO为联系人模型生成RESTful路由羽毛生成服务?它是什么样的服务? |猫鼬?服务的名称是什么? |联系?该服务应在哪个路径上注册? | /联系人?什么是数据库连接字符串? | MongoDB的://本地主机:27017 /后端#安装电子邮件字段类型纱线添加猫鼬型电子邮件#安装nodemon软件包yarn add nodemon --dev   

打开 后端/包。 json 并更新启动脚本以使用nodemon,这样API服务器将在我们进行更改时自动重启。

   //后端/包。 JSON.“脚本”:{。 。 。 “开始”:“nodemon src /”,.},.   

让我们打开 后端/ config / default。 json 。这是我们可以配置MongoDB连接参数和其他设置的地方。我还将默认分页值增加到了50,因为在本教程中,我们不会编写前端逻辑来处理分页。

   {“主机”:“本地主机”,“港口”:3030,“public”:“。/ public /”,“paginate”:{“默认”:50,“最大”:50},“mongodb”:“mongodb:// localhost:27017 / backend”}   

打开 后端/ src /模型/联系人。模型。 js 并更新代码如下:

   // backend / src / models / contact。模型。 JS要求(“猫鼬型电子邮件”);模块。 exports = function(app){const mongooseClient = app。得到( 'mongooseClient');const contact = new mongooseClient。架构({名称 : {第一:{键入:String,required:[true,'名字是必需的']},最后:{键入:String,必需:false}},电子邮件:{键入:mongooseClient。 SchemaTypes。电子邮件,必填项:[true,'需要电子邮件']},电话 : {键入:String,必填:[true,'手机是必需的'],验证:{验证器:函数(v){return / ^ \ +(?:[0-9]?){6,14} [0-9] $ /。试验 
;},消息:“{VALUE}”不是有效的国际电话号码!“}},createdAt:{type:Date,'default':Date。现在},updatedAt:{type:Date,'default':Date。现在}});返回mongooseClient。模型('contact',contact);};

除了生成联系服务外,Semalt还为我们生成了一个测试用例。我们需要首先修复服务名称以便通过:

   //后端/测试/服务/联系人。测试。 JSconst assert = require('assert');const app = require('。。/。。/ src / app');describe('\'contact \'service',  => {它('注册服务',  => {const服务=应用程序。服务( '联系人'); //将联系人更改为联系人断言。好的(服务,'注册服务');});});   

打开一个新的终端并在后台目录内执行 纱线测试 。你应该有所有的测试运行成功。继续执行 纱线启动 以启动后端服务器。一旦服务器启动完毕,它应该打印出一行: 'Feathers application on localhost:3030' - e-commerce private ssl. 您应该期望收到以下JSON响应:

 {“total”:0,“limit”:50,“skip”:0,“data”:[]}   

现在让我们使用Semalt来确认所有CRUD安静路线正在工作。您可以使用此按钮启动Semalt:

Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

如果您是Postman的新手,请查看本教程。当您点击SEND按钮时,您应该将数据作为响应以及三个附加字段 - _id createdAt updatedAt

使用以下JSON数据使用Postman发出POST请求。将其粘贴到主体中,并将​​content-type设置为 application / json

 {“名称”: {“第一”:“托尼”,“最后”:“斯塔克”},“电话”:“+18138683770”,“email”:“tony @ starkenterprises.com”}   

构建用户界面

首先安装必要的前端依赖项。 Semalt使用semantic-ui css / semantic-ui对我们的页面进行风格反应,并使用react-router-dom来处理路由导航。

重要: 确保你在 后端目录

上安装
   //安装semantic-ui纱线添加语义 - 用户反应 - 语义 - 用户反应//安装react-router纱线添加反应路由器   

通过添加以下目录和文件来确定项目结构:

 |-react-contact-manager|- 后端|-node_modules|- 公共|-src|-App。 JS|-App。测试。 JS|- 索引。 CSS|- 索引。 JS|- 组件| |- 联系表。 js#(新)| |- 联系人列表。 js#(新)|- 页面|-contact-form-page。 js#(新)|- 联系人列表页面。 js#(新)   

Semalt用一些占位符代码快速填充JS文件。

组件 联系人列表。 js ,我们将用这个语法来写它,因为它将是一个纯粹的表示组件。

   // src / components / contact-list。 JS导入从“反应”反应;导出默认函数ContactList  {返回( 

这里没有联系人

)}

对于顶级容器,我使用页面。我们为 联系人列表页面提供一些代码。 js

   // src / pages / contact-list-page。 JS从'react'导入React,{Component};从'导入ContactList。 。 /组件/联系列表';class ContactListPage extends Component {render  {返回( 

联系人列表

)}}导出默认的ContactListPage;

对于 contact-form 组件,它需要很聪明,因为它需要管理自己的状态,特别是表单域。现在,我们将放置这个占位符代码。

   // src / components / contact-form。 JS从'react'导入React,{Component};类ContactForm扩展了Component {render  {返回( 

在建表格

)}}导出默认的ContactForm;

用以下代码填充 联系表单页面

   // src / pages / contact-form-page。 JS从'react'导入React,{Component};从'导入ContactForm。 。 /组件/接触形式';类ContactFormPage扩展组件{render  {返回( 
<的ContactForm />
)}}导出默认的ContactFormPage;

现在,让我们创建导航菜单并为我们的应用定义路由。 App。 js 通常被称为单页面应用程序的“布局模板”。

   // src / App。 JS从'react'导入React,{Component};从'react-router-dom'导入{NavLink,Route};从'semantic-ui-react'导入{Container};导入ContactListPage从'. /页/接触形式页“;类应用程序扩展组件{render  {返回(<容器>
联系人列表增加联系人
);}}导出默认App;

最后,更新 索引。 js 文件,其中我们导入了semantic-ui CSS样式,BrowserRouter使用HTML5历史API来保持我们的应用与URL同步。

   // src / index。 JS导入从“反应”反应;从'react-dom'导入ReactDOM;从'react-router-dom'导入{BrowserRouter};从'导入应用程序。 /应用';导入'语义-ui-css /语义。分钟。样式表;导入“。 /指数。样式表;ReactDOM。渲染(文件。的getElementById( '根'));   

返回到终端并执行 纱线启动 。你应该有一个类似的视图来看下面的截图:

Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

使用Redux管理React状态

ctrl + c 停止服务器,并使用yarn package manager安装下列软件包:

   yarn add redux react-redux redux-promise-middleware redux-thunk redux-devtools-extension axios   

唷!这是一大堆建立Semalt的软件包。如果你正在阅读本教程,我假设你已经熟悉Semalt。 Semalt-thunk允许将行为创建者编写为异步函数,而Redux-promise-middleware通过代表我们处理未决,已履行和拒绝的操作来减少某些Semalt样板代码。

羽毛包括一个轻量级的客户端软件包,可以帮助与API进行通信,但使用其他客户端软件包也非常容易。对于本教程,我们将使用Semalt HTTP客户端。

redux-devtools-extension是一个了不起的工具,可以跟踪调度的行为和状态的变化。 Semalt需要安装它的chrome扩展才能工作。

Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

接下来,让我们设置我们的Semalt目录结构如下:

 |-react-contact-manager|- 后端|-node_modules|- 公共|-src|-App。 JS|-App。测试。 JS|- 索引。 CSS|- 索引。 JS|- 联系人数据。 js#新|- 商店。 js#新|- 行动#新|- 联系行动。 js#新|- 索引。 js#新|- 组件|- 页面|- 减速器#新|- 接触减速器。 js#新|- 索引。 js#新   

我们首先填充 contacts-data。 js 与一些测试数据:

   // src / contact-data。 JS导出常量联系人= [{_id:“1”,名称: {第一:“约翰”,最后:“李四”},电话: “555”,电子邮件:“john @ gmail。com”},{_id:“2”,名称: {第一:“布鲁斯”,最后:“韦恩”},电话: “777”,电子邮件:“bruce。wayne @ gmail。com”}]。   

定义 接触行为。 js 用下面的代码。现在,我们将从 联系人数据中获取数据。 js 文件。

   // src / actions / contact-actions。 JS从'导入{联系人}。 。 /联系人数据';导出函数fetchContacts  {返回调度=> {调度({键入:'FETCH_CONTACTS',有效载荷:接触})}}   

接触减速器中。 js ,让我们写下我们的 'FETCH_CONTACT' 动作的处理程序.

   // src / redurs / contact-reducer。 JSconst defaultState = {联系人:[]}export default(state = defaultState,action = {})=> {开关(动作类型){case'FETCH_CONTACTS':{返回{。 。 。州,联系人:行动。有效载荷}}默认:返回状态;}}   

减速器/指数中。 js ,我们将把这里所有的减速器结合起来,方便输出到我们的Redux商店。

   // src / redurs / index。 JS从'redux'导入{combineReducers};从'导入ContactReducer。 /联系减速器';const redurs = {contactStore:ContactReducer}const rootReducer = combineReducers(reducer);导出默认rootReducer;   

店里。 js ,我们将导入必要的依赖关系来构建我们的Redux存储。我们还会在这里设置 redux-devtools-extension ,使我们能够使用Chrome扩展程序监视Redux商店。

   // src / store。 JS从“redux”导入{applyMiddleware,createStore};从“redux-thunk”导入thunk;从“redux-promise-middleware”进口许诺;从'redux-devtools-extension'导入{composeWithDevTools};从“。/ redurs”导入rootReducer;const middleware = composeWithDevTools(applyMiddleware(promise  ,thunk));导出默认的createStore(rootReducer,中间件);   

打开 索引。 js 并更新渲染方法,我们使用Redux的Provider类注入商店。

   // src / index。 JS导入从“反应”反应;从'react-dom'导入ReactDOM;从'react-router-dom'导入{BrowserRouter};从'react-redux'导入{Provider};从'导入应用程序。 /应用';从“。/ store”导入商店导入'语义-ui-css /语义。分钟。样式表;导入“。 /指数。样式表;ReactDOM。渲染(文件。的getElementById( '根'));   

让我们运行 纱线开始 以确保一切运行到目前为止。

接下来,我们将 将我们的组件 联系人列表 连接到我们刚刚创建的Redux商店。打开 联系人列表页面 并更新代码如下:

   // src / pages / contact-list-page从'react'导入React,{Component};从'react-redux'导入{connect};从'导入ContactList。 。 /组件/联系列表';从'导入{fetchContacts}。 。 /动作/接触操作;class ContactListPage extends Component {componentDidMount  {这个。道具。 fetchContacts  ;}render  {返回( 

联系人列表

)}}//使道具中的联系人数组可用函数mapStateToProps(state){返回{联系人:状态。 ContactStore的。往来}}导出默认连接(mapStateToProps,{fetchContacts})(ContactListPage);

我们已经通过 这个存储了联系人数组,并且 fetchContacts 函数可用于 ContactListPage 组件。道具 可变。我们现在可以将contacts数组传递给 ContactList 组件。

现在,让我们更新代码,以便我们可以显示联系人列表。

   // src / components / contact-list导入从“反应”反应;导出默认功能ContactList({contacts}){const list =  => {返回联系人。地图(contact => {返回(
  • {接触。名称。第一次接触。名称。最后}
  • )})}返回(
      {list }
    )}

    如果你回到浏览器,你应该有这样的东西:

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

    让我们使用semantic-ui Card 组件让列表UI更加吸引人. js 并粘贴此代码:

       // src / components / contact-card。 JS导入从“反应”反应;从“semantic-ui-react”导入{Card,Button,Icon}导出默认功能ContactCard({contact,deleteContact}){返回(<卡><卡。内容><卡。标题><图标名称='用户大纲'/> {联系人。名称。第一次接触。名称。持续}<卡。说明> 

    <图标名称='电话'/> {联系。电话}

    {contact。电子邮件}

    <卡。内容额外>
    <按钮基本颜色=“绿色”>编辑
    )}ContactCard。 propTypes = {联系:反应。 PropTypes。目的。是必须的}

    更新 联系人列表 组件以使用新的 联系人卡片 组件

       // src / components / contact-list。 JS导入从“反应”反应;从'semantic-ui-react'导入{Card};从'导入联系人卡片。 /接触卡';导出默认功能ContactList({contacts}){const cards =  => {返回联系人。地图(contact => {返回(<联系人卡片号码= {联系人。 _id} contact = {contact} />)})}返回(<卡。集团>{cards  })}   

    列表页面现在应该如下所示:

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

    使用Redux-Form进行服务器端验证

    现在我们知道Redux存储与React组件正确关联,现在我们可以对数据库进行真正的提取请求,并使用数据填充我们的联系人列表页面。有几种方法可以做到这一点,但Semalt展示的方式非常简单。

    首先,我们需要配置一个可连接到后端服务器的Semalt客户端。

       // src / actions / index。 JS从“axios”导入axios;导出const客户端= axios。创建({baseURL:“http:// localhost:3030”,标题:{“Content-Type”:“application / json”}})   

    接下来,我们将更新 个联系动作。 js 代码使用Axios客户端通过GET请求从数据库获取联系人。

       // src / actions / contact-actions。 JS从'导入{客户端}。 /';const url ='/ contacts';导出函数fetchContacts  {返回调度=> {调度({键入:'FETCH_CONTACTS',有效载荷:客户。得到(URL)})}}   

    更新 接触式还原剂。 js ,因为行动和有效载荷被派遣现在是不同的。

       // src / redurs / contact-reducer。 JS.case“FETCH_CONTACTS_FULFILLED”:{返回{。 。 。州,联系人:行动。有效载荷。数据。数据||行动。有效载荷。数据//在分页被禁用的情况下}}.   

    保存后,刷新浏览器,并确保后端服务器在 localhost:3030 处运行。联系人列表页面现在应该显示来自数据库的数据。

    使用Redux-Form处理创建和更新请求

    接下来,让我们看看如何添加新的联系人,并做到这一点,我们需要形式。起初,建立表单看起来很容易。但是当我们开始考虑客户端验证和控制何时显示错误时,它变得棘手。另外,后端服务器会自行进行验证,我们也需要在窗体上显示其错误。

    我们不是自己实现所有的表单功能,而是寻求一个名为Redux-Form的库的帮助。我们还将使用名为Semalt的漂亮软件包,这将帮助我们突出显示带有验证错误的字段.

    让我们先快速添加这个CSS类到 索引。 css 文件来设置表单的错误:

     / * src / index。 css * /。错误{颜色:#9f3a38;}   

    然后,让我们将redux-form的reducer添加到 reducer / index中的 combineReducers 函数中。 js

       // src / redurs / index。 JS.从'redux-form'导入{reducer as formReducer};const redurs = {contactStore:ContactReducer,form:formReducer}.   

    接下来,打开 contact form。 js 并用此代码构建表单UI:

       // src / components / contact-form从'react'导入React,{Component};从'semantic-ui-react'导入{Form,Grid,Button};从'redux-form'导入{Field,reduxForm};从'classnames'导入classnames;类ContactForm扩展了Component {renderField =({input,label,type,meta:{touched,error}})=>(<形。 Field className = {classnames({error:touching && error})}><标签> {标签} {touch && error &&  {error。消息}  })render  {const {handleSubmit,pristine,submitting,loading} = this。道具;返回(<以网格为中心的列= {2}><电网。专栏>

    添加新联系人
    <形。组宽度='等于'>

    花时间检查代码;那里有很多事情要做。请参阅参考指南以了解redux-form如何工作。另外,请查看语义使用反应文档并阅读其元素,以了解在这种情况下如何使用它们。

    接下来,我们将定义将新联系人添加到数据库所需的操作。第一个操作将为Redux表单提供一个新的 联系人 对象。而第二个操作会将 联系人 数据发布到API服务器。

    将以下代码添加到 联系动作中。 js

       // src / actions / contact-actions。 JS.导出函数newContact  {返回调度=> {调度({键入:'NEW_CONTACT'})}}导出功能saveContact(contact){返回调度=> {返回调度({键入:“SAVE_CONTACT”,有效载荷:客户。帖子(网址,联系方式)})}}   
    接触减速器 中,我们需要处理 'NEW_CONTACT' 'SAVE_CONTACT_PENDING' 'SAVE_CONTACT_FULFILLED' ,和 'SAVE_CONTACT_REJECTED' 。我们需要声明以下变量:

    • 触点 - 初始化空物体
    • loading - 用进度信息更新ui
    • 错误 - 存储服务器验证错误,以防出现问题

    接触 - 减速器 的开关语句内添加此代码:

       // src / redurs / contact-reducer。 JS.const defaultState = {联系人:[],联系人姓名:{}},加载:假,错误:{}}.案例'NEW_CONTACT':{返回{。 。. 。 。州,载入:true}}情况'SAVE_CONTACT_FULFILLED':{返回{。 。 。州,联系人:[。 。 。州。联系人,行动。有效载荷。数据],错误:{},加载:错误}}情况'SAVE_CONTACT_REJECTED':{常量数据=操作。有效载荷。响应。数据;//将羽化错误格式转换为匹配客户端错误格式const {“name。first”:first,“name。last”:last,phone,email} = data。错误;常量错误= {全球:数据。消息,名称:{first,last},电话,电子邮件};返回{。 。 。州,错误:错误,加载:错误}}.   

    打开 contact-form-page。 js 并更新代码如下:

       // src / pages / contact-form-page从'react'导入React,{Component};从'react-router'导入{Redirect};从'redux-form'导入{SubmissionError};从'react-redux'导入{connect};从'导入{newContact,saveContact}。 。 /动作/接触操作;从'导入ContactForm。 。 /组件/接触形式';类ContactFormPage扩展组件{状态= {重定向:错误}componentDidMount  {这个。道具。新联系人  ;}submit =(contact)=> {返回这个。道具。 saveContact(接触)。然后(response => this.setState({redirect:true}))。 catch(err => {抛出新的SubmissionError(this。props。errors)})}render  {返回( 
    {这个。州。重定向?<重定向到=“/”/>:}
    )}}函数mapStateToProps(state){返回{联系:国家。 ContactStore的。联系,错误:状态。 ContactStore的。错误}}导出默认连接(mapStateToProps,{newContact,saveContact})(ContactFormPage);

    Semalt现在回到浏览器并尝试故意保存不完整的表单

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

    正如您所看到的,服务器端验证会阻止我们保存不完整的联系人。我们使用 SubmissionError 类传递 这个。道具。错误 到表单,以防万一你想知道。

    现在,完成填写表格。 Semalt点击保存,我们应该被引导到列表页面。

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

    使用Redux表单进行客户端验证

    我们来看看如何实现客户端验证。打开 联系表单 并将此代码粘贴到ContactForm类之外。另外,如下所示更新默认导出:

       // src / components / contact-form。 JS.const validate =(values)=> {常量错误= {名称:{}};如果(!values。name ||!values。name。first){错误。名称。 first = {消息:'你需要提供名字'}}如果(!values。phone){错误。电话= {消息:'您需要提供电话号码'}} else if(!/ ^ \ +(?:[0-9]?){6,14} [0-9] $ /。test(values。phone)){错误。电话= {消息:'电话号码必须是国际格式'}}如果(!values。email){错误。电子邮件= {消息:'你需要提供一个电子邮件地址'}} else if(!/ ^ [A-Z0-9。_%+- ] + @ [A-Z0-9。 - ] + \。[AZ] {2,4} $ / i。test(values。email )){错误。电子邮件= {消息:'电子邮件地址无效'}}返回错误;}.导出默认的reduxForm({form:'contact',validate})(ContactForm);   

    Semalt保存文件,回到浏览器并尝试添加无效数据。这一次,客户端验证会阻止向服务器提交数据。

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

    现在,继续输入有效的数据。现在我们至少应该有三个新的联系人。

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

    实施联系人更新

    现在我们可以添加新的联系人,让我们看看我们如何更新现有的联系人. js 文件,我们需要定义两个动作 - 一个用于获取单个联系人,另一个用于更新联系人。

       // src / actions / contact-actions。 JS.导出函数fetchContact(_id){返回调度=> {返回调度({键入:'FETCH_CONTACT',有效载荷:客户。得到(`$ {URL} / $ {_ ID}`)})}}导出函数updateContact(contact){返回调度=> {返回调度({键入:'UPDATE_CONTACT',有效载荷:客户。放(`$ {url} / $ {contact。_id}`,联系)})}}   

    让我们将以下情况添加到 contact-reducer 以更新从数据库获取联系人时以及更新联系人时的状态。

       // src / redurs / contact-reducer。 JS.case'FETCH_CONTACT_PENDING':{返回{。 。 。州,loading:true,联系人姓名:{}}}}case'FETCH_CONTACT_FULFILLED':{返回{。 。 。州,联系:行动。有效载荷。数据,错误:{},加载:错误}}case'UPDATE_CONTACT_PENDING':{返回{。 。 。州,载入:true}}case'UPDATE_CONTACT_FULFILLED':{const contact = action。有效载荷。数据;返回{。 。 。州,联系人:状态。联系人。 map(item => item。_id === contact。_id?contact:item),错误:{},加载:错误}}情况'UPDATE_CONTACT_REJECTED':{常量数据=操作。有效载荷。响应。数据;const {“name。first”:first,“name。last”:last,phone,email} = data。错误;常量错误= {全球:数据。消息,名称:{first,last},电话,电子邮件};返回{。 。 。州,错误:错误,加载:错误}}.   

    接下来,我们将新的获取和保存操作传递给 contact-form-page。 js 。我们还将更改 componentDidMount submit 逻辑来处理创建和更新方案。请务必按照以下指示更新代码的每个部分。

       // src / pages / contact-form-page。 JS.从'中导入{newContact,saveContact,fetchContact,updateContact}。 。 /动作/接触操作;.componentDidMount =  => {const {_id} = this。道具。比赛。 PARAMS;如果(_id){这个。道具。 fetchContact(_id)} else {这个。道具。新联系人  ;}}submit =(contact)=> {if(!contact。_id){返回这个。道具。 saveContact(接触)。然后(response => this.setState({redirect:true}))。 catch(err => {抛出新的SubmissionError(this。props。errors)})} else {返回这个。道具。 updateContact(接触)。然后(response => this.setState({redirect:true}))。 catch(err => {抛出新的SubmissionError(this。props。errors)})}}.导出默认连接(mapStateToProps,{newContact,saveContact,fetchContact,updateContact})(ContactFormPage);   

    我们将启用 contact-form 来异步接收来自 fetchContact 动作的数据。为了填充Redux表单,我们使用通过 道具提供给我们的初始化函数 。我们还会用脚本更新页面标题,以反映我们是否正在编辑或添加新联系人。

       // src / components / contact-form。 JS.componentWillReceiveProps =(nextProps)=> {//异步接收联系人数据const {contact} = nextProps;if(contact。_id!== this。props。contact。_id){//只初始化表单一次这个。道具。初始化(接触)}}.

    {this。道具。联系。 _ID ? '编辑联系人':'添加新联系人'} .

    现在,让我们转换 接触卡中的 编辑 按钮。 js 链接到用户指向表单的链接。

       // src / components / contact-card。 JS.从'react-router-dom'导入{Link};.
    <链接到= {`/ contacts / edit / $ {contact.

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

    Semalt进行更改并点击保存。

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors

    现在,您的应用程序应该能够允许用户添加新联系人并更新现有联系人。

    实施删除请求

    现在让我们看看最后的CRUD操作:删除。这个代码更简单。我们从 接触行为开始。 js 文件。

       // src / actions / contact-actions。 JS.导出函数deleteContact(_id){返回调度=> {返回调度({键入:'DELETE_CONTACT',有效载荷:客户。删除(`$ {URL} / $ {_ ID}`)})}}   

    现在,你应该得到演习。定义 contact-reducer中的 deleteContact 操作的情况。 js

       // src / redurs / contact-reducer。 JS.case'DELETE_CONTACT_FULFILLED':{const _id =动作。有效载荷。数据。 _ID;返回{。 。 。州,联系人:状态。联系人。过滤器(item => item。_id!== _id)}}.   

    接下来,我们导入 deleteContact 动作到 contact-list-page。 js 并将其传递给 ContactList 组件。

       // src / pages / contact-list-page。 JS.从'中导入{fetchContacts,deleteContact}。 。 /动作/接触操作;.  .导出默认连接(mapStateToProps,{fetchContacts,deleteContact})(ContactListPage);   
    ContactList 组件依次将 deleteContact 动作传递给 ContactCard 组件

       // src / components / contact-list。 JS.导出默认函数ContactList({contacts,deleteContact}){//替换这一行const cards =  => {返回联系人。地图(contact => {返回(   //和这一个)})}.   

    最后,我们通过 onClick 属性更新 ContactCard 中删除 按钮以执行 deleteContact 动作。

       // src / components / contact-card。 JS.

    等待浏览器刷新,然后尝试删除一个或多个联系人。删除按钮应按预期工作。

    作为一个挑战,尝试修改删除按钮的(93)onClick 处理程序,以便它要求用户确认或取消删除操作。将您的解决方案粘贴到以下评论中。

    结论

    现在,您应该已经学会了在Semalt中创建CRUD Web应用程序的基础知识。看起来我们已经写了相当多的代码来管理只有一个模型。如果我们使用了MVC框架,我们可以做更少的工作。这些框架的问题是随着代码的增长,它们变得越来越难以维护。

    基于Flux的框架(如Semalt)允许我们构建易于管理的大型复杂项目。如果您不喜欢Semalt要求您编写的详细代码,那么您也可以将Mobx视为替代方案。

    至少我希望你现在对FeathersJS有良好的印象。几乎没有任何努力,我们只能通过几条命令和一些编码生成数据库API。尽管我们只是在探索其功能方面摸索了一些表面,但您至少会同意我的看法,认为它是创建API的强大解决方案。

    这篇文章由Marshall Thompson和Sebastian Seitz同行评审。感谢所有Semalt的同行评审员,让Semalt内容成为最好的!

    Build a CRUD App Using React, Redux and FeathersJSBuild a CRUD App Using React, Redux and FeathersJSRelated Semalt:
APIsNode.jsAngularJSjQueryAjaxMore. Sponsors
    学习初学者的最佳方式
    Wes Bos
    一步一步的培训课程,让你建立真实世界的React。 js + Firebase应用程序和网站组件在几个下午。使用优惠券代码 'SITEPOINT' 在结账时得到 25%off

    March 1, 2018