用途:为使用 Relay 进行数据获取的 React 组件提供编写规范,帮助开发者采用地道模式,避免常见反模式。
主要能力与核心原则:数据共置(组件通过 GraphQL 片段声明自身数据需求)、数据屏蔽(组件只能访问自己片段中显式选择的字段)、组合(片段逐层组合成查询)、渲染前获取(在组件渲染前启动请求)、规范化存储(按 ID 缓存,变更返回数据后相关组件自动重渲染)。
使用方式:Relay 使用预编译编译器读取代码中的 graphql 模板字面量,生成运行时产物与 TypeScript/Flow 类型。配置查找顺序为项目根目录的 relay.config.{json,js,mjs,ts} 或 package.json 中的 relay 键。修改 graphql 模板或 Relay Resolver 文档块后运行 npx relay-compiler;生成文件位于 generated/ 目录,切勿手动编辑。可运行 npx relay-compiler config-json-schema 输出配置 JSON Schema。
关键决策规则:查询应放在路由入口,不要放在 hook 中;使用 usePreloadedQuery 配合 useQueryLoader 或 loadQuery,在事件处理、路由切换或应用初始化时启动获取;不要在 useEffect 中调用 loadQuery;不要为查询变量设置空默认值;组件展示服务端数据时应声明片段并接收片段引用;变更响应中应展开消费组件的片段而非逐字段选择;错误处理推荐 @throwOnFieldError 与 @catch;分页使用 @argumentDefinitions、@refetchable、@connection 三指令组合;客户端状态优先使用 Relay Resolvers。
重要反模式:不要把 Relay 数据复制进 React state,也不要把片段 key 存入 state;不要在父查询中获取全部数据再传原始对象;不要在变更后做不必要的 refetch。
正确性建议:依赖存储状态的乐观更新使用 optimisticUpdater;影响面广的变更使用 invalidateRecord() 或 invalidateStore();显式处理数据陈旧(queryCacheExpirationTime 或事件式失效);设置 artifactDirectory 以保留类型安全;优先使用 @updatable;实时数据使用订阅而非轮询。
命名约定:片段为 ComponentName_propName,查询为 ComponentNameQuery,变更为 ComponentNameMutation,操作名必须与所在模块文件名匹配,否则编译报错。
文档与限制:Relay 在 node_modules/relay-runtime/llm-docs/ 提供 LLM 友好文档(v20.1.1 之后可用),旧版本可从 GitHub 获取。性能相关指导见配套的 relay-performance 技能。本技能为规范建议,具体 API 细节需查阅对应文档页面。