# @churnkey/react 中文文档

规范地址：https://npmcn.com/package/%40churnkey/react/

版本：0\.10\.0
npm 元数据更新时间：2026-11-02T17:50:56.687Z
中文译文更新时间：2026-11-09T15:43:47.515Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40churnkey/react
原文对照：https://npmcn.com/package/%40churnkey/react/?lang=original
项目主页：https://github.com/churnkey/sdk#readme
源码仓库：https://github.com/churnkey/sdk

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：1 MB，57 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：react ^18\.0\.0 \|\| ^19\.0\.0，react-dom ^18\.0\.0 \|\| ^19\.0\.0
- 首次发布：2026-04-30T16:32:54.465Z
- 最新版本发布：2026-11-02T17:50:56.318Z
- 近 30 天下载量：4873（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：23（近 12 个月 23 个）

## 中文简介

生产准备取消流量 滴入组件,无头钩,或完全定制. 单独工作或与Churnkey一起工作,以保留AI动力.

## 安装

```sh
npm install @churnkey/react
```

也可以使用：`pnpm add @churnkey/react`、`yarn add @churnkey/react`、`bun add @churnkey/react`

## README

# @ churnkey/ 反应

React 的取消流量组件 。 调查、提议、反馈和确认。 准备用出盒子,在需要的时候可以完全定制.

开源. 可选连接到 [Rn克](https://churnkey.co/) 分析学和人工智能能力保留.

## 安装

```bash
npm install @churnkey/react
```

## 创建取消流量

导入组件和样式表,定义您的步骤,并处理结果.

```tsx
import { CancelFlow } from '@churnkey/react'
import '@churnkey/react/styles.css'

<CancelFlow
  steps={[
    {
      type: 'survey',
      title: 'Why are you leaving?',
      reasons: [
        {
          id: 'expensive',
          label: 'Too expensive',
          offer: {
            type: 'discount',
            couponId: 'STRIPE_SAVE20',  // your coupon ID
            percentOff: 20,             // for the UI
            durationInMonths: 3,        // for the UI
          },
        },
        {
          id: 'not-using',
          label: 'Not using it enough',
          offer: { type: 'pause', months: 2 },
        },
        { id: 'missing', label: 'Missing features' },
      ],
    },
    { type: 'feedback', title: 'Anything else?' },
    { type: 'confirm' },
  ]}
  handleDiscount={async (offer) => myBilling.applyCoupon(offer.couponId)}
  handlePause={async (offer) => myBilling.pause({ months: offer.result?.months ?? offer.months })}
  handleCancel={async () => myBilling.cancel()}
  onClose={() => setOpen(false)}
/>
```

当客户选择"太贵"时,SDK会显示折扣报价. 如果他们接受了, `handleDiscount` 运行。 如果他们拒绝所有的报价和确认, `handleCancel` 运行.

## 改变外观

SDK飞船的轻而易举和黑暗计划. `'auto'` 跟踪用户的OS偏好,并对变化作出反应.

```tsx
<CancelFlow
  appearance={{ colorScheme: 'auto' }}
  steps={steps}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

覆盖通过 `appearance.variables`同样的价值在两种方案中都适用——一次设定出你的品牌颜色,然后随处可见.

```tsx
appearance={{
  variables: { colorPrimary: '#7c3aed', borderRadius: '12px' },
}}
```

基于类的样式( Tailwind, CSS 模块), 使用 `classNames`数字 :

```tsx
classNames={{
  modal: 'max-w-lg shadow-2xl',
  overlay: 'bg-black/60 backdrop-blur-sm',
}}
```

## 替换组件

换掉任何UI的一部分。 SDK处理导航和状态;你处理渲染.

```tsx
<CancelFlow
  steps={steps}
  components={{
    ReasonButton: ({ reason, isSelected, onSelect }) => (
      <button
        onClick={() => onSelect(reason.id)}
        className={isSelected ? 'border-blue-500 bg-blue-50' : 'border-gray-200'}
      >
        {reason.label}
      </button>
    ),
  }}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

您可以替换 `Modal`, (中文(简体) ), `CloseButton`, (中文(简体) ), `BackButton`,步骤组件`Survey`, (中文(简体) ), `Offer`, (中文(简体) ), `Feedback`, (中文(简体) ), `Confirm`, (中文(简体) ), `Success`, (中文(简体) ), `ReasonButton`每发价类型的组件(`DiscountOffer`, (中文(简体) ), `PauseOffer`, (中文(简体) ), `PlanChangeOffer`, (中文(简体) ), `TrialExtensionOffer`, (中文(简体) ), `ContactOffer`, (中文(简体) ), `RedirectOffer`),以及 `StackedOffer` 为一对报价.

## 添加自定义步骤

台阶系统开放. 使用任意字符串作为步骤类型,然后为它注册一个组件.

```tsx
<CancelFlow
  steps={[
    { type: 'survey', reasons: [
      { id: 'seats', label: 'Too many seats',
        offer: { type: 'change-seats', data: { minSeats: 1 } } },
    ]},
    { type: 'nps', title: 'One quick question', data: { scale: 10 } },
    { type: 'feedback' },
    { type: 'confirm' },
  ]}
  customComponents={{
    'nps': ({ step, onNext }) => (
      <NpsRating scale={step.data.scale} onSubmit={(score) => onNext({ score })} />
    ),
    'change-seats': ({ offer, onAccept }) => (
      <SeatAdjuster onConfirm={(seats) => onAccept({ seats })} />
    ),
  }}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

自定义步骤像内置步骤一样导航 。 自定义要约在选择匹配原因时出现 。 无论你传递给什么 `onNext(result)` 或者说 `onAccept(result)` 现身 `offer.result` 在你身边 `onAccept` 处理器,并记录在分析会话中(如: `customStepResults[stepType]` 步骤, `acceptedOffer.customOfferResult` (关于要约).

## 预建定制出价组件

如果你不想自己建定制的UI, 导入一个预建的 `@churnkey/react/recipes`它们采用与内置报价相同的造型系统,并将结果通过 `onAccept`,所以你只执行计费部分.

```tsx
import { TermExtensionOffer, PassthroughOffer } from '@churnkey/react/recipes'

<CancelFlow
  customComponents={{
    // "Delay your next charge by N days". Reads offer.data.days, shows the
    // new renewal date, passes { days } through onAccept.
    annual_term_extension: TermExtensionOffer,
    // Copy + accept/decline, nothing else. Register it for any offer type
    // whose substance lives entirely in the flow-authored copy; offer.data
    // passes through as the result.
    scheduled_transfer: PassthroughOffer,
    immediate_transfer: PassthroughOffer,
  }}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

组件位于子路径导出后, 因此除非导入, 否则不会添加到您的捆绑中 。 要进行完整的演示文稿控制,请从 `packages/react/examples/` 转而进入你的密码库 从那里拥有它.

## 无头去

如果要完全控制UI,直接使用钩子.

```tsx
import { useCancelFlow } from '@churnkey/react/headless'

function MyCancelPage() {
  const flow = useCancelFlow({ steps, onAccept: handleOffer, onCancel: handleCancel })

  if (flow.step === 'survey') {
    return (
      <div>
        {flow.reasons.map((r) => (
          <button key={r.id} onClick={() => flow.selectReason(r.id)}>{r.label}</button>
        ))}
        <button onClick={flow.next} disabled={!flow.selectedReason}>Continue</button>
      </div>
    )
  }

  if (flow.step === 'offer' && flow.currentOffer) {
    return (
      <div>
        <h2>{flow.currentOffer.copy.headline}</h2>
        <button onClick={flow.accept}>Accept</button>
        <button onClick={flow.decline}>No thanks</button>
      </div>
    )
  }

  // ... feedback, confirm, success
}
```

钩子返回当前状态( T)`step`, (中文(简体) ), `reasons`, (中文(简体) ), `currentOffer`, (中文(简体) ), `feedback`, (中文(简体) ), `outcome`, (中文(简体) ), `isProcessing`和行动`selectReason`, (中文(简体) ), `next`, (中文(简体) ), `back`, (中文(简体) ), `accept`, (中文(简体) ), `decline`, (中文(简体) ), `cancel`, (中文(简体) ), `close`) (中文(简体) ).

在象征性模式中,钩子会留下一对报价,除非你通过 `stackedOffers: true`; 见 [报价对等](https://npmcn.com/package/%40churnkey/react/#readme-pairs-of-offers)。 。 。 .

## 添加分析

创建一个 [免费 Churnkey 账户](https://app.churnkey.co/register?intent=sdk) 并通过你的 `appId`。SDK记录每个会话,这样你就可以知道为什么客户取消,提供工作,以及你的储蓄率是什么样子.

```tsx
<CancelFlow
  appId="app_xxx"
  customer={{ id: 'cus_123' }}
  steps={steps}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

仅 `customer.id` 需要时间。 关于收入衡量标准,也通过订阅数据:

```tsx
<CancelFlow
  appId="app_xxx"
  customer={{ id: 'cus_123', email: 'jane@acme.com' }}
  subscriptions={[{
    id: 'sub_456',
    start: '2024-06-01',
    status: { name: 'active', currentPeriod: { start: '2025-04-01', end: '2025-05-01' } },
    items: [{ price: { id: 'price_pro', amount: { value: 2999 } } }],
  }]}
  steps={steps}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

你的步骤和召回不会改变。 不需要后端工作 .

当客户接受要约、确认取消或完成(放弃)之前关闭模式时,会话记录。 从自定义步骤通过的数据 `onNext(result)` 与会议同时进行.

为了保持交通 出你的生产分析,通过 `mode="test"`数字 :

```tsx
<CancelFlow
  appId="app_xxx"
  customer={{ id: 'cus_123' }}
  mode={process.env.NODE_ENV === 'production' ? 'live' : 'test'}
  steps={steps}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

默认为 `'live'`。如果您的矿石连接到一个 [花边沙盒](https://docs.stripe.com/sandboxes) 而不是经典测试模式,通过 `mode="sandbox"` 而不是服务器侧的帐单操作 使用您的沙盒证书。 在指使模式中,指使模式优先——它是服务器签名的,不能被压倒客户端侧面.

## 让Churnkey处理账单

在Churnkey仪表板上连接您的计费供应商(Stripe,Chargebee等),Churnkey可以应用折扣,暂停订阅,并代表您取消. 在您的服务器上生成一个令牌以认证会话 .

```typescript
// Server
import { Churnkey } from '@churnkey/node'

const ck = new Churnkey({ appId: 'app_xxx', apiKey: 'sk_xxx' })
const token = ck.createToken({ customerId: 'cus_123' })
```

```tsx
// Client
<CancelFlow
  appId="app_xxx"
  customer={{ id: 'cus_123', email: 'jane@acme.com' }}
  subscriptions={[...]}
  session={token}
  onAccept={async (offer) => console.log('Applied:', offer)}
  onCancel={async () => router.push('/goodbye')}
/>
```

在此模式下,取消流由Churnkey仪表板配置. 您的自定义组件和外观设置继续 .

### 处理器对听众

两种回叫,用名来区分:

-   **`handle<Type>`** - 运行动作。 替换 Churnkey 在服务器上所做的 。 在本地模式( 无令牌 ) 中, 这是唯一运行动作 .
-   **`on<Type>`** ——行动后起火,无论是谁指挥. 副作用只有——分析,回放,土司.

```tsx
<CancelFlow
  session={token}
  // Handler: defining handlePause tells the SDK NOT to call its own
  // server-side pause; you run the action instead. Skip handle* and
  // Churnkey takes the action automatically in token mode.
  handlePause={async (offer, customer) => {
    await myBilling.pause({ months: offer.result?.months ?? offer.months })
  }}
  // Listener: fires after the pause completes (whoever ran it).
  onPause={(offer, customer) => analytics.track('paused', { months: offer.result?.months ?? offer.months })}
  onAccept={(offer) => analytics.track('offer_accepted', { type: offer.type })}
  onCancel={() => router.push('/goodbye')}
/>
```

可用的处理器 : `handleDiscount`, (中文(简体) ), `handlePause`, (中文(简体) ), `handlePlanChange`, (中文(简体) ), `handleTrialExtension`, (中文(简体) ), `handleCancel`。可用的听众 : `onDiscount`, (中文(简体) ), `onPause`, (中文(简体) ), `onPlanChange`, (中文(简体) ), `onTrialExtension`, (中文(简体) ), `onCancel`,加上包罗万象 `onAccept` 任何被接受的报价.

单位 **本地模式** (没有标志),没有服务器动作——处理者做活. 单位 **符号模式**定义一个操作员选择退出运行动作的Churnkey,并将工作还给你.

### 报价对等

报价可携带第二个报价(`offer.stackedOffer`),设置在仪表板上. SDK显示每张出价一张卡和一个单个"接受两个出价"按钮;通过: `StackedOffer` 组件槽.

Churnkey只向一个显示两种报价的UI发送一对. 和你自己一样 `Offer` 组件,或 a `customComponents` 输入内置要约类型,对子不包含在流量中,除非您也通过 `StackedOffer`与 `useCancelFlow`,通过 `stackedOffers: true` 一旦你的UI让 `offer.stackedOffer`。 。 。 .

-   没有处理器,令牌模式在一项请求中同时适用两种要约. 在暂停或延长审判后,第二次提议在暂停或审判结束后开始.
-   与处理者,每出价通过自己的处理者,先出价,但退价最后出价. 如果第二顺位的报价失败了, 流量仍然完成, `acceptedOffer.stackedOffer.stackStatus` 实值 `'failed'` 财务报告和审定财务报表 `failedOfferType` 列出不适用的报价。 只有Churnkey在暂停或试运行时可以持有第二个报价,因此在本地模式中,当一个处理者覆盖任一报价时,一对其第二个报价等待被忽略出流量. 在象征性模式中,当处理者只覆盖其一项要约时,一对也会被排除在外,因为Churnkey只将一对要约与另一对一起应用.
-   听众和 `onAccept` 得到每个报价 自己, 一旦适用报价.
-   A 类 `StackedOffer` 组件接受配对并有一个结果: `months` 用于暂停和 `planId` 计划改变。 每个报价 `result` 只有自己的选择,加上你通过的任何其他钥匙.

### 传递客户/订阅数据并附带一个令牌

你可以通过 `customer` 财务报告和审定财务报表 `subscriptions` 合并 `session` 用客户端数据来丰富会话记录的Churnkey还没有(海关元数据,当前计划价格等). 指使牌上签名的客户ID保持权威;直接数据填补了空白.

```tsx
<CancelFlow
  appId="app_xxx"
  customer={{ id: 'cus_123', email: 'jane@acme.com', metadata: { plan: 'pro' } }}
  subscriptions={[...]}
  session={token}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

### 混合本地和服务器步骤

你可以通过两个 `session` 财务报告和审定财务报表 `steps` 以覆盖特定的服务器配置 :

```tsx
<CancelFlow
  session={token}
  steps={[
    { type: 'confirm', title: 'We hate to see you go' },
    { type: 'nps', title: 'Quick question', data: { scale: 10 } },
  ]}
  customComponents={{ 'nps': NpsStep }}
  onAccept={handleOffer}
  onCancel={handleCancel}
/>
```

本地步骤按类型覆盖 。 未在服务器配置中的步骤会被附加 .

## 进口

```tsx
import { CancelFlow } from '@churnkey/react'              // drop-in component
import { useCancelFlow } from '@churnkey/react/headless'   // headless hook
import { CancelFlowMachine } from '@churnkey/react/core'   // state machine, no React
import { TermExtensionOffer } from '@churnkey/react/recipes' // prebuilt custom-offer components
```

## 许可证

麻省理工学院

## 常见问题

### @churnkey/react 是什么？

生产准备取消流量 滴入组件,无头钩,或完全定制\. 单独工作或与Churnkey一起工作,以保留AI动力\.

### 如何安装 @churnkey/react？

在项目目录运行 npm install @churnkey/react，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（^18\.0\.0 \|\| ^19\.0\.0）、react-dom（^18\.0\.0 \|\| ^19\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @churnkey/react 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @churnkey/react 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @churnkey/react 可以商用吗？

@churnkey/react 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @churnkey/react 的下载量有多少？

根据 npm 官方下载统计，@churnkey/react 在 2026/10/10 – 2026/11/08 这 30 天内被下载 4,873 次，日均约 162 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @churnkey/react 还在维护吗？

最新版本 0\.10\.0 发布于 2026/11/03（6 天前）；至今共发布 23 个版本，其中过去 12 个月发布了 23 个；首次发布于 2026/05/01。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

