mcpField
R
react-call

react-call

github.com/desko27开发1.4k181 次安装11 周前更新
代码仓库

关于 react-call

这是 react-call v2.x 的使用指南,可让 React 组件从异步代码中被调用并返回结果。它帮助 React 开发者将此模式用于确认框、选择器等需要向调用方返回值的界面。

主要功能

  1. 01命令式调用并解析为结果
  2. 02调用堆栈与单例 upsert 模式
  3. 03Root 与单次调用属性指引
  4. 04异步 MutationFlow 指引
  5. 05SSR 与挂载约束

适用场景

  1. 01等待确认操作的结果
  2. 02从异步代码打开选择器或表单模态框
  3. 03显示单例 Toast 或进度界面

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/desko27/react-call --skill react-call

安装后在 Claude Code 中输入/react-call确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
host.md
mutation-flow.md
ssr-and-lazy.md
types.md

详细介绍

react-call

createCallable() 可将 React 组件变成可供 await 的对象:你可以从任何位置命令式地调用它,它会解析为一个值。本技能涵盖 react-call v2.x — 请检查使用方的 package.json,如果版本不同,则以已安装的版本为准。

权威参考(任务执行时请勿获取;仅作指引):https://react-call.desko.dev

何时使用 react-call(以及何时不使用)

适合使用:当某段 UI 在概念上会向调用方返回一个值,且你想在异步代码中 await 该值时:确认框、对话框、表单模态框、Toast/通知、上下文菜单、选择器、多步骤向导。

可以建议使用:如果 react-call 尚未成为依赖项,但任务适合使用它 — 那么运行 npm install react-call。

不要强行推广:如果已有其他方案且运行良好 — 可以提及 react-call 是一种选择,但不要在未被要求时重构。对于不返回任何内容的纯展示型组件,以及更适合通过路由实现的整页流程,请勿使用。

术语(请使用这些准确术语)

  • Callable — createCallable() 返回的值。它既是一个 React 组件(挂载 <Confirm />),也是一个方法命名空间(call、upsert、end、update)。不要称它为“模态框/对话框/组件”。
  • Root — Callable 的挂载形式:裸的 <Confirm />。不要称为“provider/portal/outlet”。
  • Call — 一次命令式调用(Confirm.call({...})),解析为一个 Response。
  • Stack — Root 渲染的活动 Call 有序列表(不是“队列”)。
  • CallContext — 组件接收的 call 属性:{ end, ended, key, index, stackSize, root }。不是 React“Context”。
  • Upsert — 单例式 Call(upsert());MutationFlow — 来自 react-call/mutation-flow 的异步提交生命周期。

模型:Declare → Root → Call

import { createCallable } from 'react-call'

interface Props { message: string }
type Response = boolean

// 1. Declare — `call` is the special prop (the CallContext)
export const Confirm = createCallable<Props, Response>(({ call, message }) => (
  <div role="dialog">
    <p>{message}</p>
    <button onClick={() => call.end(true)}>Yes</button>
    <button onClick={() => call.end(false)}>No</button>
  </div>
))

// 2. Root — mount the Callable once, somewhere always rendered (e.g. App.tsx)
//    <Confirm />

// 3. Call & await — from anywhere
const accepted = await Confirm.call({ message: 'Continue?' })

泛型为 createCallable<Props, Response, RootProps>(均可选)。

决策指南

  • call 与 upsert — call() 每次都会打开一个新的 Call(它们会叠加)。upsert() 是单例:首次调用会创建 Call,后续的 upsert() 会更新同一个 Call,并返回同一个 promise。Toast、进度提示、加载状态 — 任何最多只应有一个实例的内容,都适合使用 upsert。
  • useMutationFlow — 当 Call 提交异步操作且发生错误时应保持打开状态,以便用户重试,就适合使用它。它会管理 pending,并且只会在显式调用 call.end() 时关闭。参见 references/mutation-flow.md。
  • Root props 与 Call props — 每个 Call 独有的数据放入 call() 的 props;所有 Call 共享的数据(主题、当前用户)放入 RootProps,传递给 <Confirm userName="…" /> 并通过 call.root 读取。
  • 从调用方结束/更新 — Confirm.end(promise, value)/Confirm.update(promise, partialProps) 针对一个 Call;省略 promise 则会影响所有活动 Call。

硬性规则(常见故障)

  • 每个 Callable 只能有一个 Root。 在两个仍处于活动状态的位置挂载 <Confirm />,会在调用 call() 时抛出 "Multiple instances of found!"。对于 Storybook/Ladle 和其他多预览宿主,请使用 react-call/host — 参见 references/host.md。
  • call() 只能在客户端调用。 在 SSR 期间运行会抛出 "No found!"。在 Next.js/RSC 中,将 createCallable 所在文件标记为 'use client'。参见 references/ssr-and-lazy.md。
  • 调用时 Root 必须已挂载且处于活动状态。 如果 Root 位于条件性卸载的子树中,从外部调用 call() 会抛出 "No found!"。请将它挂载在较高层级(布局/应用外壳)。
  • 退出动画需要将卸载延迟作为 createCallable 的第 2 个参数,然后根据 call.ended 控制 CSS: createCallable(Component, 500) + className={call.ended ? 'leaving' : ''}。

反模式

  • 按路由或功能分别放置 <Confirm /> → 会抛出多 Root 错误。只挂载一次。
  • 在服务端组件中或渲染期间调用 Confirm.call(...) → 会抛出错误。 请在客户端的事件处理程序或副作用中调用。
  • 对单例(如 toast)重复使用 call() → 会创建重复实例。请使用 upsert()。
  • 将 Callable 当作普通组件并传入 props 来渲染——它就是 Root;传给 <Confirm /> 的 props 是 RootProps,而不是 Call props。

参考

评论

支持 Markdown