首页/新闻资讯/正文详情

WordPress.com 阅读器推荐博客开关解析:`useFeedRecommendationsMutation` Hook 实战指南

发布时间:2026/9/25 8:12:19 来源:云帆数科 栏目:资讯中心
WordPress.com 阅读器推荐博客开关解析:`useFeedRecommendationsMutation` Hook 实战指南
前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载本文基于 wp-calypso 仓库中 client/data/reader/use-feed-recommendations-mutation/README.md 编写深入讲解 Reader阅读器模块中用于管理推荐博客Recommended Blogs列表的自定义 React Hook。你将掌握它的 API 签名、乐观更新与失败自动回滚的完整数据流、底层 REST 端点以及它在订阅管理页与 Feed 详情页中的真实接入方式可直接照搬到自己的功能开发中。背景Reader Hooks 与推荐博客列表在 wp-calypso 中client/data/reader/目录集中存放着阅读器相关的数据层 Hook如 use-feed-recommendations-query、use-tag-stats.ts 等。其中use-feed-recommendations-mutation这个目录专用于管理当前用户推荐博客列表的成员状态——即把某个博客加入或移出用户自己的推荐列表。需要特别注意文档中的一句关键提示这里说的 sites 实际上就是 feeds。推荐列表的成员单位是 feedRSS/站点订阅源因此 Hook 的入参是feedId而不是siteId。在实现中这个列表被固化在一个名为recommended-blogs的阅读列表read list里常量定义于 index.tsconst RECOMMENDED_BLOGS_SLUG recommended-blogs;API 参考签名与返回值Hook 的完整签名定义在 index.tsexport const useFeedRecommendationsMutation ( feedId: number ): useFeedRecommendationsMutationResult { ... }参数参数类型说明feedIdnumber要管理推荐状态的 feed ID注意调用方常需用Number(...)转换因为很多数据源给出的是字符串 ID返回值useFeedRecommendationsMutationResultinterface useFeedRecommendationsMutationResult { isRecommended: boolean; // 当前推荐状态由 React Query 缓存推导 isUpdating: boolean; // 操作是否进行中 canToggle: boolean; // 是否允许切换决定开关是否可用 toggleRecommended: () void; // 切换推荐状态的函数 }四个返回值中isRecommended是只读状态、toggleRecommended是唯一动作配合isUpdating与canToggle两个护栏可以让消费组件无需关心任何请求细节。实战用法把推荐开关接到界面上README 给出的示例是一个订阅列表行组件用Toggle开关展示Recommended blog状态const SiteSubscriptionRow ( { feed_ID: feedId, /* other props */ } ) { const { isRecommended, toggleRecommended } useFeedRecommendationsMutation( Number( feedId ) ); return ( div classNamesubscription-row {/* Site info */} Toggle checked{ isRecommended } onChange{ toggleRecommended } labelRecommended blog / /div ); };这个示例在仓库中有两个真实落点值得对照阅读1. 订阅管理页的站点行client/landing/subscriptions/components/site-subscriptions-list/site-subscription-row.tsx// Use custom hook for recommended site functionality const { isRecommended, toggleRecommended } useFeedRecommendationsMutation( Number( feedId ?? 0 ) );这里需要注意一个真实场景的细节订阅接口返回的feed_id可能为空字符串因此调用方做了feedId ?? 0兜底再交给Number()转换。开关本体是wordpress/components的FormToggle并且用disabled{ ! currentUserName || typeof currentUserName ! string }与canToggle双保险地禁用了未登录状态见 site-subscription-row.tsx。切换时会先调用toggleRecommended()再通过recordRecommendToggle上报 Tracks 分析事件site-subscription-row.tsx。2. Reader Feed 详情页头部client/blocks/reader-feed-header/follow.tsxconst { isRecommended, isUpdating: isRecommendationPending, toggleRecommended, } useFeedRecommendationsMutation( feedId as number );在这里Hook 与封装好的 RecommendButton 组件配合按钮文案会在 Recommended 与 Recommend this blog 之间切换isLoading{ isRecommendationPending }在请求期间禁用按钮且只有当用户following || isRecommended时才展示推荐入口follow.tsx。状态如何计算三个布尔值的来源isRecommended完全由 React Query 缓存推导Hook 内部不维护任何本地 state推荐状态全部来自查询缓存index.tsconst { data: itemsData } useQuery( { ...readListItemsAllQuery( currentUserName, RECOMMENDED_BLOGS_SLUG ), enabled: !! currentUserName !! recommendedBlogsList?.ID, } ); const isRecommended !! itemsData?.items?.some( ( item ) Number( item.feed_ID ) Number( feedId ) );即只要recommended-blogs列表的 items 中存在feed_ID feedId的条目isRecommended即为true。由于乐观更新直接修改同一份缓存isRecommended会在点击瞬间翻转无需等待网络返回。canToggle前置条件检查canToggle 的计算要求同时满足两个条件const canToggle Boolean( currentUserName typeof currentUserName string recommendedBlogsList?.ID );存在已登录的当前用户名getCurrentUserName来自 Redux已找到当前用户自己的recommended-blogs列表具备ID。也就是说未登录用户、或尚未创建该列表的用户开关会被禁用。isUpdating任一请求进行中即锁定const { mutate: addFeed, isPending: isAdding } useMutation( addReadListFeedMutation( queryClient ) ); const { mutate: deleteFeed, isPending: isDeleting } useMutation( deleteReadListFeedMutation( queryClient ) ); const isUpdating isAdding || isDeleting;isUpdating用于防止并发切换——toggleRecommended内部第一道防线就是if ( ! canToggle || isUpdating || ... ) return;index.ts。行为机制乐观更新与失败自动回滚README 中写道useFeedRecommendationsMutationreads the recommended-blogs list items from React Query (readListItemsAllQuery) and toggles membership throughaddReadListFeedMutation/deleteReadListFeedMutation。Both mutations apply optimistic updates against the same query cache and roll back on failure, so the UI reverts automatically when the API call errors out.下面从源码拆解这条完整链路。数据读取两级查询Hook 先订阅当前用户的所有阅读列表index.tsconst { data: subscribedListsData } useQuery( { ...readSubscribedListsQuery(), enabled: !! currentUserName, } ); const recommendedBlogsList currentUserName ? subscribedListsData?.lists.find( ( list ) list.owner currentUserName list.slug RECOMMENDED_BLOGS_SLUG ) : undefined;readSubscribedListsQuery定义于 packages/api-queries/src/read-lists.ts其 queryKey 为[read, lists, subscribed]底层请求GET /read/lists时还携带了create_recommended_blogs_list: true参数——即首次拉取订阅列表时服务端会自动为用户创建 recommended-blogs 列表见 packages/api-core/src/read-lists/fetchers.ts。拿到recommendedBlogsList.ID之后才启用第二级查询读取列表全部条目const { data: itemsData } useQuery( { ...readListItemsAllQuery( currentUserName, RECOMMENDED_BLOGS_SLUG ), enabled: !! currentUserName !! recommendedBlogsList?.ID, } );readListItemsAllQuerypackages/api-queries/src/read-list-items.ts一次拉取 2000 条number: 2000并携带meta: site,feed,tag完整元数据对应GET /read/lists/{user}/{slug}/items见 packages/api-core/src/read-list-items/fetchers.ts。它还针对list_not_found用户尚无该列表时返回的永久 404做了特殊处理该错误不重试而普通瞬时错误最多重试 3 次与旧版>yarn test-client client/data/reader/use-feed-recommendations-mutation对应的测试文件是 client/data/reader/use-feed-recommendations-mutation/test/index.test.ts它用nock拦截真实 HTTP 请求通过renderHookQueryClientProviderReduxProvider组装出最小运行环境覆盖了五类关键行为初始非推荐状态列表不含该 feed 时isRecommended false且canToggle true已推荐状态列表含{ feed_ID: feedId }时isRecommended true无当前用户username null时canToggle false无 recommended-blogs 列表subscribedLists: []时canToggle false端点行为调用toggleRecommended()后分别断言POST /rest/v1.2/read/lists/testuser/recommended-blogs/feeds/new与POST /rest/v1.2/read/lists/testuser/recommended-blogs/feeds/{feedId}/delete确实被发出index.test.ts。测试中的mockList直接复刻了真实列表结构ID: 456、owner: testuser、slug: recommended-blogs而readListItemsAllQuery的缓存数据则按{ list_ID, success, items, page, number: 2000, total_items }的响应格式注入方便你在阅读测试时对照ReadListItemsResponse类型packages/api-core/src/read-list-items/types.ts。边界情况与使用注意事项综合 README 与源码实际接入时有几点需要留意feedId 必须为数字订阅接口等多处返回的是字符串 ID务必先Number(...)转换否则some比较与请求路径都会出错未登录 / 列表缺失时开关自动禁用canToggle已涵盖这两种情况无需消费方重复判断但订阅管理页仍额外叠加了disabled属性做双保险list_not_found不重试新用户首次进入时 recommended-blogs 列表可能尚未在缓存中readListItemsAllQuery对此做了专门的retry: false分支避免无意义的重复请求列表项是多态的ReadListItem可能携带feed_ID、site_ID或tag_ID乐观更新产生的占位条目可能只含其中一个字段所有字段均为可选/可空见 types.ts因此判断推荐状态时按feed_ID匹配是正确做法切换期间的防抖toggleRecommended在isUpdating为真时直接返回配合按钮的disabled{ isLoading }可避免快速连点导致的重复请求。小结useFeedRecommendationsMutation是 wp-calypso 数据层查询 乐观 mutation模式的代表性实现通过两级 React Query 查询订阅列表 → 列表条目推导只读状态通过共享同一 queryKey 的 add/delete mutation 实现即时 UI 反馈并在失败时用快照回滚。理解这条链路你就能在 Reader 相关功能中复用它也能参考 packages/api-queries/src/read-list-items.ts 的模式为自己的列表管理功能写出同样健壮的乐观更新代码。赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐Qwen Code 多模型提供方配置完全指南modelProviders 与 providerProtocol 深度解析Qwen Code 多模型提供方配置完全指南modelProviders 与 providerProtocol 深度解析 导读 Qwen Code 是一款运行人工智能AI Agent代码智能体工具调用交互助手CLIQwenAria国际化支持多语言界面使用指南Aria国际化支持多语言界面使用指南 Aria作为一款简单高效的下载工具提供了全面的国际化支持让全球用户都能轻松使用母语界面进行操作。本文将详细介绍如何配Mobile-Agent跨平台GUI智能体的革命性突破Mobile Agent跨平台GUI智能体的革命性突破 在数字生活日益复杂的今天我们每天需要在多个设备间切换——手机处理社交消息电脑完成工作文档平板浏览人工智能大模型AI AgentGUI 自动化自主智能体上一篇如何解决会议记录漏记难题TMSpeech带来的实时语音转文字高效解决方案下一篇zteOnu中兴光猫命令行管理工具全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Windows硬件性能验证:CPU/GPU/内存/存储/散热五维实测指南
Windows硬件性能验证:CPU/GPU/内存/存储/散热五维实测指南

1. 项目概述:这不是跑个分那么简单,而是给整台Windows电脑做一次“全科体检”你手头这台Windows电脑,开机慢、渲染卡顿、游戏掉帧、导出视频总在最后5%崩溃——这些症状背后,往往不是软件问题,而是硬件在悄悄“罢工”。… · 2026/9/25 8:12:13

企业创新激励机制报告:从诊断到落地的实操方法
企业创新激励机制报告:从诊断到落地的实操方法

在企业做管理咨询和内部创新推进这些年,我接过最多的需求之一,就是“帮我们出一份创新激励机制报告”。听起来像是一份文档交付物,但真正做过的人都知道,企业要的不是纸面上的“报告”两个字,而是一套能回答“创新为什… · 2026/9/25 8:12:07

TopDown Shooter设计思路:从战斗手感、AI状态机到关卡与成长系统
TopDown Shooter设计思路:从战斗手感、AI状态机到关卡与成长系统

最近在整理手头这个TopDown Shooter项目时,把整套设计思路重新过了一遍。这个品类看起来门槛很低——不就是一个人在俯视角地图里开枪打怪吗?但真做下来,里面涉及到的战斗手感、AI行为、关卡节奏、成长数值、表现反馈,每个环节拆开… · 2026/9/25 8:12:01

Java变量深度解析:内存模型、作用域、常量与命名规范
Java变量深度解析:内存模型、作用域、常量与命名规范

变量大概是Java里第一个绕不开、又被大多数教程一句话带过的概念。我见过工作两三年的开发,能把集合框架、JVM调优聊得头头是道,但你问他int a 10;这一行到底发生了什么,他反而含糊其辞。变量看起来简单,简单到我们每天都在写&am… · 2026/9/25 8:53:51

Tekton Pipeline 依赖库 go-fed/httpsig:HTTP Signatures 请求/响应签名与验证实现解析
Tekton Pipeline 依赖库 go-fed/httpsig:HTTP Signatures 请求/响应签名与验证实现解析

云原生CI/CDDevOps后端 【免费下载链接】pipeline A cloud-native Pipeline resource. 项目地址: https://gitcode.com/gh_mirrors/pipelin/pipeline 点击查看 免费下载 本文以 Tekton Pipeline 仓库中 vendored 的第三方库 go-fed/httpsig(v1.1.0&… · 2026/9/25 8:53:45

业务开发视角的可观测体系建设:从日志、链路到告警的实战指南
业务开发视角的可观测体系建设:从日志、链路到告警的实战指南

那天晚上十一点半,业务群突然炸了:下单成功率掉了快一半,用户反馈进来一堆。我作为订单模块的业务开发,打开监控大盘一看,CPU 正常、内存正常、服务平均耗时也正常,整个系统看起来"健康"得不能再… · 2026/9/25 8:53:45

Java毕设实战:基于SpringBoot+SSM的蛋糕购物平台系统解析
Java毕设实战:基于SpringBoot+SSM的蛋糕购物平台系统解析

很多Java学习者第一次真正接触到“一个完整系统”,就是从做这类商城项目开始的。云与糖蛋糕购物平台系统就是这样一个很典型的JavaSpringBootSSM项目:用户端能注册登录、按分类浏览蛋糕、把心仪的甜品加入购物车、下单模拟支付;管理端能维护商… · 2026/9/25 8:53:45

ETSI EN 300 132-1 V2.1.1电源端口合规设计实战指南
ETSI EN 300 132-1 V2.1.1电源端口合规设计实战指南

简介:本资源为欧洲电信标准协会(ETSI)发布的正式标准文件《EN 300 132-1 V2.2.1(2019-03)》,聚焦信息和通信技术(ICT)设备交流电源接口的环境工程规范,面向ICT设备制造商… · 2026/9/25 8:53:20

有名的奢侈品名表回收品牌企业、服务不错的奢侈品名表回收企业、有名的奢侈品名表回收专业公司用户力荐
有名的奢侈品名表回收品牌企业、服务不错的奢侈品名表回收企业、有名的奢侈品名表回收专业公司用户力荐

有名专业的奢侈品名表回收,靠谱连锁品牌更安心很多想要出手闲置奢侈品名表的用户,都希望找到透明靠谱的专业平台,东莞市好岱贸易有限公司旗下品牌好岱中古汇,是一家深耕二手奢侈品回收行业的全国连锁直营平台,始终坚持… · 2026/9/25 8:53:14

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码