在上一部分我们添加了创建新页面的功能,
在这一部分中,我们将添加一个删除功能添加到我们的应用程序中。
以下是我们将要构建的内容:
让我们从创建删除页面按钮
组件和更新我们的用户界面页面列表
组件:
从“@wordpress/components”导入{Button};从“@wordpress/html-entities”导入{decodeEntities};const DeletePageButton=()=>(<按钮变量=“primary”>删除</按钮>)函数PagesList({hasResolved,pages}){if(!已解决){return<微调器/>;}if(!页?长度){return无结果;}返回(<table className=“wp-list-table widefat fixed striped table-view-list”><头部><tr><td>标题</td>操作</td></tr></thead><t车身>{pages?.map((page)=>(<tr键={page.id}><td>{decodeEntities(page.title.rendered)}</td><td><div className=“表单按钮”><PageEditButton pageId={page.id}/>{/*↓这是PagesList组件中的唯一更改*/}<DeletePageButton pageId={page.id}/></div></td></tr>) ) }</tbody></表格>);}
现在PagesList应该是这样的:
在古腾堡数据中,我们使用删除实体记录
行动。它发送请求,处理结果,并在Redux状态下更新缓存的数据。
以下是您可以尝试在浏览器的开发工具中删除实体记录的方法:
//我们需要一个有效的页面ID来调用deleteEntityRecord,所以让我们使用getEntityRegords获取第一个可用的页面ID。const pageId=wp.data.select('core').getEntityRecords('postType','page')[0].id;//现在,让我们删除该页面:const promise=wp.data.dispatch('core').deleteEntityRecord('postType','page',pageId);//当API请求成功或失败时,promise得到解决或拒绝。
REST API请求完成后,您会注意到其中一个页面已从列表中消失。这是因为该列表由使用选择()
钩子和select(coreDataStore).getEntityRecords('postType','page')
选择器。每当基础数据发生变化时,列表都会使用新数据重新呈现。那很方便!
让我们在以下情况下执行该操作删除页面按钮
单击:
const DeletePageButton=({pageId})=>{const{deleteEntityRecord}=useDispatch(核心数据存储);const handleDelete=()=>删除实体记录('postType','page',pageId);返回(<Button variant=“primary”onClick={handleDelete}>删除</按钮>);}
单击删除按钮。让我们用一个<微调器/>
组件类似于我们在本教程前几部分中所做的操作。
我们需要正在删除实体记录
选择器。它类似于是保存实体记录
我们已经在中看到的选择器第3部分:返回真的
或假
并且从不发出任何HTTP请求:
const DeletePageButton=({pageId})=>{// ...const{isDeleting}=useSelect(选择=>({isDeleting:选择(coreDataStore).isDeletingEntityRecord('postType','page',pageId),}),[页面ID])返回(<Button variant=“primary”onClick={handleDelete}disabled={isDeleting}>{正在删除吗(<><微调器/>正在删除。。。</>):'删除'}</按钮>);}
下面是实际情况:
我们乐观地认为删除手术总是会成功的。不幸的是,在后台,它是一个RESTAPI请求,可能会以多种方式失败:
- 网站可能会关闭。
- 删除请求可能无效。
- 在此期间,该页面可能已被其他人删除。
为了告诉用户这些错误何时发生,我们需要使用获取最后一个实体删除错误
选择器:
//用实际页面ID替换9wp.data.select('core').getLastEntityDeleteError('postType','page',9)
以下是我们如何将其应用于删除页面按钮
:
从'react'导入{useEffect};const DeletePageButton=({pageId})=>{// ...const{错误,/*…*/}=useSelect(选择=>({错误:select(coreDataStore).getLastEntityDeleteError('postType','page',pageId),// ...} ),[页面ID]);使用效果(()=>{if(错误){//显示错误}},[错误])// ...}
这个错误
对象来自@wordpress/api-回迁
并包含有关错误的信息。它具有以下属性:
消息
–人类可读的错误消息,例如帖子ID无效
.
代码
–基于字符串的错误代码,如rest_post_invalid_id
。要了解所有可能的错误代码,您需要参阅/v2/页
端点的源代码.
数据
(可选)–错误详细信息,包含代码
包含失败请求的HTTP响应代码的属性。
有很多方法可以将该对象转换为错误消息,但在本教程中,我们将显示错误消息
.
WordPress已经建立了使用小吃店
组件。这是它的样子在Widgets编辑器中:
让我们在插件中使用相同类型的通知!这有两个部分:
- 显示通知
- 正在调度通知
显示通知
我们的应用程序只知道如何显示页面,但不知道如何显示通知。让我们来说说吧!
WordPress方便地为我们提供了呈现通知所需的所有React组件。A类组件名为小吃店
表示单个通知:
我们不会使用小吃店
不过,这是直接的。我们将使用小吃店列表
组件,它可以使用平滑动画显示多个通知,并在几秒钟后自动隐藏它们。事实上,WordPress使用的组件与Widgets编辑器和其他wp-admin页面中使用的组件相同!
让我们创建自己的通知
组件:
从“@wordpress/components”导入{SnackbarList};从“@wordpress/notices”导入{store as noticesStore};函数通知(){常量通知=[];//我们马上回来!返回(<小吃店列表通知={notices}className=“components-editor-notices__snackbar”/>);}
基本结构已就位,但它呈现的通知列表为空。我们如何填充它?我们将使用与WordPress相同的软件包:@wordpress/通知
.
方法如下:
从“@wordpress/components”导入{SnackbarList};从“@wordpress/notices”导入{store as noticesStore};函数通知(){const通知=使用选择((select)=>select(noticesStore).getNotices(),[]);const{removeNotice}=useDispatch(noticesStore);const snackbarNotices=notices.filter(({type})=>type===“snackbar”);返回(<小吃店列表通知={snackbarNotices}className=“components-editor-notices__snackbar”onRemove={removeNotice}/>);}函数MyFirstApp(){// ...返回(<div>{/* ... */}<通知/></div>);}
本教程的重点是管理页面,不会详细讨论上述代码片段。如果你对@wordpress/通知
,的手册页是一个很好的起点。
现在,我们已经准备好告诉用户可能发生的任何错误。
发送通知
有了SnackbarNotices组件,我们就可以发送一些通知了!方法如下:
从'react'导入{useEffect};从“@wordpress/notices”导入{store as noticesStore};函数DeletePageButton({pageId}){const{createSuccessNotice,createErrorNotice}=useDispatch(noticesStore);//如果传递存储句柄,useSelect将返回选择器列表//而不是回调:const{getLastEntityDeleteError}=useSelect(核心数据存储)const-handleDelete=async()=>{const success=等待deleteEntityRecord('postType','page',pageId);if(成功){//告诉用户操作成功:createSuccessNotice(“页面已删除!”{type:“snackbar”,} );}其他{//我们直接使用选择器获取deleteEntityRecord后的新错误//已失败。const lastError=getLastEntityDeleteError(“postType”,“page”,pageId);const message=(lastError?.message | |'出现错误。')+'请刷新页面,然后重试。'//告诉用户操作到底是如何失败的:创建错误通知(消息{type:“snackbar”,} );}}// ...}
伟大的!删除页面按钮
现在已完全意识到错误。让我们看看该错误消息的作用。我们将触发一个无效的删除并让其失败。一种方法是将页面ID
数量众多:
函数DeletePageButton({pageId,onCancel,onSaveFinished}){pageId=pageId*1000;// ...}
刷新页面并单击任意删除
按钮,您应该会看到以下错误消息:
好极了!我们现在可以删除pageId=pageId*1000;
行。
现在让我们尝试实际删除一个页面。刷新浏览器并单击“删除”按钮后,您将看到以下内容:
就这样!
所有部件都就位了,太棒了!以下是我们在本章中所做的所有更改:
从'react'导入{useState,useEffect};从“@wordpress/data”导入{useSelect,useDispatch};从“@wordpress/components”导入{Button、Modal、TextControl};函数MyFirstApp(){const[searchTerm,setSearchTerm]=使用状态(“”);const{pages,hasResolved}=useSelect((选择)=>{常量查询={};如果(searchTerm){query.search=搜索术语;}const selectorArgs=['postType','page',query];const pages=select(coreDataStore).getEntityRecords(…selectorArgs);返回{页,hasResolved:选择(coreDataStore).hasFinishedResolution('获取实体记录',选择器参数,),};},[searchTerm],);返回(<div><div className=“list-controls”><SearchControl onChange={setSearchTerm}value={searchTerm}/><页面创建按钮/></div><PagesList hasResolved={hasResorved}pages={pages}/><通知/></div>);}函数SnackbarNotices(){const通知=使用选择((select)=>select(noticesStore).getNotices(),[]);const{removeNotice}=useDispatch(noticesStore);const snackbarNotices=notices.filter(({type})=>type=='snackbar');返回(<小吃店列表通知={snackbarNotices}className=“components-editor-notices__snackbar”onRemove={removeNotice}/>);}函数PagesList({hasResolved,pages}){if(!已解决){return<微调器/>;}if(!页?.长度){return无结果;}返回(<table className=“wp-list-table widefat fixed striped table-view-list”><头部><tr><td>标题</td>操作</td></tr></thead><t车身>{pages?.map((page)=>(<tr键={page.id}><td>{page.title.rendered}</td><td><div className=“表单按钮”><PageEditButton pageId={page.id}/><DeletePageButton pageId={page.id}/></div></td></tr>) ) }</tbody></表格>);}函数DeletePageButton({pageId}){const{createSuccessNotice,createErrorNotice}=useDispatch(noticesStore);//如果传递存储句柄,useSelect将返回选择器列表//而不是回调:const{getLastEntityDeleteError}=useSelect(核心数据存储)const handleDelete=async()=>{const success=等待deleteEntityRecord('postType','page',pageId);if(成功){//告诉用户操作成功:createSuccessNotice(“页面已删除!”{type:“snackbar”,} );}其他{//我们直接使用选择器获取此时的错误。//假设我们得到这样的错误://const{lastError}=useSelect(函数(){/*…*/});//那么,在handleDelete中lastError将为null。//为什么?因为我们会引用计算出来的版本//甚至在调用handleDelete之前。const lastError=getLastEntityDeleteError(“postType”,“page”,pageId);const message=(lastError?.message | |'出现错误。')+'请刷新页面,然后重试。'//告诉用户操作到底是如何失败的:创建错误通知(消息{type:“snackbar”,} );}}const{deleteEntityRecord}=useDispatch(核心数据存储);const{isDeleting}=useSelect(选择=>({isDeleting:选择(coreDataStore).isDeletingEntityRecord('postType','page',pageId),} ),[页面ID]);返回(<Button variant=“primary”onClick={handleDelete}disabled={isDeleting}>{正在删除吗(<><微调器/>正在删除。。。</>):'删除'}</按钮>);}