wp-calypso 数据查询组件实战:QuerySiteConnectionStatus 获取 Jetpack 站点连接状态
2026/9/24 14:57:49 网站建设 项目流程
  • 前端
  • CMS

【免费下载链接】wp-calypso

The JavaScript and API powered WordPress.com

项目地址:https://gitcode.com/gh_mirrors/wp/wp-calypso
点击查看免费下载

<QuerySiteConnectionStatus />是 wp-calypso(WordPress.com 的 JavaScript 与 API 驱动型前端)中用于自动发起网络请求、获取 Jetpack 站点与 WordPress.com 连接状态的数据查询组件。它不渲染任何 DOM,只负责把 Redux 全局状态树中的数据准备好,供同级兄弟组件消费。读完本文,你将掌握该组件的用法、props 契约、底层 Redux 数据流(action → reducer → selector)以及对应单元测试的验证方式,可直接在自有 Calypso 区块中落地复用。

组件定位:数据查询组件(Query Component)设计模式

在 wp-calypso 的client/components/data/目录下,存在一系列以Query前缀命名的组件,它们遵循统一的“查询组件”设计模式:渲染即发起请求,无渲染输出,数据写入全局状态树

QuerySiteConnectionStatus正是该模式在“站点连接状态”场景下的实现,其完整源码位于 client/components/data/query-site-connection-status/index.jsx。从源码结构看,该组件是一个典型的函数式组件,核心逻辑只有三件事:

  1. 通过useSelector之外的方式(这里直接使用getState)读取当前是否已在请求该站点的连接状态;
  2. 若尚未在请求,则派发requestConnectionStatus( siteId )action;
  3. 返回null,即不渲染任何元素。
// client/components/data/query-site-connection-status/index.jsx(节选) const request = ( siteId ) => ( dispatch, getState ) => { if ( siteId && ! isRequestingSiteConnectionStatus( getState(), siteId ) ) { dispatch( requestConnectionStatus( siteId ) ); } }; export default function QuerySiteConnectionStatus( { siteId } ) { const dispatch = useDispatch(); useEffect( () => { dispatch( request( siteId ) ); }, [ dispatch, siteId ] ); return null; }

关键设计点:

  • 副作用收敛在useEffectsiteId变化会重新触发请求,因此切换站点时组件会自动拉取新站点的连接状态;
  • 幂等防重isRequestingSiteConnectionStatus守卫保证了同一站点在请求进行中不会被重复发起请求;
  • 无渲染:组件返回null,页面布局完全不受影响,与兄弟组件解耦。

使用方式:渲染即触发请求

按官方 README(client/components/data/query-site-connection-status/README.md)的说明,使用该组件只需渲染它并传入siteId。它不接受任何 children,也不向页面渲染任何元素,你可以把它与依赖全局状态中已获取数据的兄弟组件并排使用:

import QuerySiteConnectionStatus from 'calypso/components/data/query-site-connection-status'; export default function ExampleSiteComponent( { siteConnectionStatus, translate } ) { return ( <div> <QuerySiteConnectionStatus siteId={ 12345678 } /> { siteConnectionStatus ? translate( 'Site is connected' ) : translate( 'Site is not connected' ) } </div> ); }

Props 契约

Prop类型必填说明
siteIdNumber需要获取 WordPress.com 连接状态的站点 ID

该契约同样在组件源码中通过 PropTypes 声明(PropTypes.number.isRequired),缺失siteId会在开发环境抛出 PropTypes 警告。

底层数据流:从 action 到 Redux 状态

组件本身只是“触发器”,真正的数据获取由client/state/site-connection/模块完成。整体数据流为:

渲染 QuerySiteConnectionStatus(siteId) │ ▼ dispatch(requestConnectionStatus(siteId)) // actions.js │ ▼ SITE_CONNECTION_STATUS_REQUEST // 标记 requesting[siteId] = true │ ▼ GET /rest/v1.1/jetpack-blogs/{siteId}/test-connection │ ├── 成功 ──► SITE_CONNECTION_STATUS_RECEIVE + REQUEST_SUCCESS └── 失败 ──► SITE_CONNECTION_STATUS_REQUEST_FAILURE │ ▼ reducer 更新 state.siteConnection.{items, requesting} │ ▼ selector 读取(getSiteConnectionStatus / isRequestingSiteConnectionStatus)

Action:请求连接状态

client/state/site-connection/actions.js 中的requestConnectionStatus( siteId )是一个 Redux thunk,它:

  1. 先派发SITE_CONNECTION_STATUS_REQUEST标记请求开始;
  2. 通过wp.req.get( '/jetpack-blogs/${ siteId }/test-connection' )调用 WordPress.com REST API 的test-connection端点;
  3. 成功后派发SITE_CONNECTION_STATUS_RECEIVE(携带response.connected布尔值)与SITE_CONNECTION_STATUS_REQUEST_SUCCESS
  4. 失败时派发SITE_CONNECTION_STATUS_REQUEST_FAILURE(携带 error)。
export const requestConnectionStatus = ( siteId ) => { return ( dispatch ) => { dispatch( { type: SITE_CONNECTION_STATUS_REQUEST, siteId } ); return wp.req .get( `/jetpack-blogs/${ siteId }/test-connection` ) .then( ( response ) => { dispatch( { type: SITE_CONNECTION_STATUS_RECEIVE, siteId, status: response.connected } ); dispatch( { type: SITE_CONNECTION_STATUS_REQUEST_SUCCESS, siteId } ); } ) .catch( ( error ) => { dispatch( { type: SITE_CONNECTION_STATUS_REQUEST_FAILURE, siteId, error } ); } ); }; };

Reducer:状态如何落库

client/state/site-connection/reducer.js 通过combineReducers组合了两个子 reducer,最终挂载到全局状态树的state.siteConnection键(注册逻辑见 client/state/site-connection/init.js):

  • items:以siteId为键存储连接状态布尔值。收到SITE_CONNECTION_STATUS_RECEIVE时写入[siteId]: status;同一站点重复接收时覆盖旧值,不同站点则累积(实现为不可变展开...state)。
  • requesting:以siteId为键标记请求进行中状态。REQUESTtrueREQUEST_SUCCESS/REQUEST_FAILUREfalse

Selector:兄弟组件如何消费数据

数据落地后,业务组件通过 selector 读取:

  • client/state/selectors/get-site-connection-status.js:返回state.siteConnection.items[ siteId ] ?? null。站点未知或尚未收到状态时返回null,收到后返回布尔值。这正是上方示例中siteConnectionStatus的数据来源;
  • client/state/selectors/is-requesting-site-connection-status.js:返回state.siteConnection.requesting[ siteId ] ?? false,用于组件内的防重判断。

测试验证:行为被单元测试完整锁定

该模块的测试覆盖了 action 与 reducer 两个层面,是理解组件行为的权威佐证。

Action 测试

client/state/site-connection/test/actions.js 使用useNockmock REST 请求,验证了三种行为:

  • 发起时:派发SITE_CONNECTION_STATUS_REQUEST
  • 成功时:依次派发SITE_CONNECTION_STATUS_RECEIVE(status 为true)与SITE_CONNECTION_STATUS_REQUEST_SUCCESS,mock 的响应体形如{ connected: true, message: 'User is connected.' }
  • 失败时:派发SITE_CONNECTION_STATUS_REQUEST_FAILURE,其中 error 的 message 为接口返回的'This user is not authorized to test connection for this blog.'(对应 403 场景)。

这从侧面印证了接口契约:test-connection端点返回connected布尔字段,未授权用户会收到 403。

Reducer 测试

client/state/site-connection/test/reducer.js 使用deepFreeze保证不可变性,验证了:

  • items默认空对象、写入、多站点累积、同站点覆盖四种行为;
  • requesting默认空对象、置true、成功后置false、失败后置false四种行为。

实战建议与注意事项

  • 配合 selector 使用:组件只负责触发请求,展示逻辑应通过getSiteConnectionStatus等 selector 从 Redux 状态树读取,避免在渲染层直接持有请求结果;
  • siteId必须有效:源码中requestsiteId做了 truthy 判断,空值不会发起请求;PropTypes 亦要求必填,建议在渲染前确保站点对象已就绪;
  • 请求状态区分null(未知/未请求)与false(已确认未连接)语义不同,界面上的“加载中 / 未连接”态应分开处理;
  • 只读使用:该组件仅用于在页面中触发数据获取,无需(也不应)直接修改仓库中的 Redux 模块。

小结

QuerySiteConnectionStatus是 wp-calypso 查询组件模式的精炼示例:无渲染、副作用收敛、幂等防重,配合client/state/site-connection/的 action/reducer/selector 三层结构,将 Jetpack 站点的 WordPress.com 连接状态查询无缝接入全局状态管理。理解它的完整链路(组件 → action → reducer → selector)之后,你可以轻松类比到client/components/data/下的其他查询组件,快速上手 Calypso 的数据获取体系。

  • 前端
  • CMS

【免费下载链接】wp-calypso

The JavaScript and API powered WordPress.com

项目地址:https://gitcode.com/gh_mirrors/wp/wp-calypso
点击查看免费下载
上一篇:阅读APP书源一键导入终极指南:3种快速方法+高质量小说阅读书源全解析
下一篇:LiteGraph.js CI/CD流程优化:测试与部署加速

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询