跳转到内容

React 绑定

Terminal window
npm install fatigue-kit fatigue-kit-react

在浏览器入口创建一次持久化实例。点击按钮后,只有 tryConsume 允许才展示优惠;Hooks 不在 render 或 mount 时消费。

import { useState } from 'react'
import { createRoot } from 'react-dom/client'
import { createFatigue } from 'fatigue-kit'
import { localStorageAdapter } from 'fatigue-kit/adapters/local-storage'
import { FatigueProvider, useFatigueState } from 'fatigue-kit-react'
const fatigue = createFatigue({ storage: localStorageAdapter() })
function Coupon() {
const [open, setOpen] = useState(false)
const popup = useFatigueState('coupon', [
{ max: 1, every: 'day' },
{ max: 3, window: '7d' },
{ cooldown: '4h' },
])
function showCoupon() {
if (popup.tryConsume().allowed) setOpen(true)
}
return (
<>
<button onClick={showCoupon}>展示优惠</button>
<p>{popup.result.allowed ? '可以展示' : '已达到频控上限'}</p>
{open && (
<section aria-label="优惠">
<p>你的优惠内容</p>
<button onClick={() => setOpen(false)}>关闭</button>
</section>
)}
</>
)
}
const container = document.getElementById('root')
if (container) {
createRoot(container).render(
<FatigueProvider value={fatigue}><Coupon /></FatigueProvider>,
)
}

生产弹窗请使用应用已有的无障碍对话框组件;这里的 section 仅演示条件渲染。

单独调用 createFatigue() 默认使用内存,重新创建实例会丢失记录。此浏览器示例通过 localStorage 保留刷新前的状态。namespace 和 key 决定记录范围,用户或活动变化时请设计隔离键。存储失败可能使频控降级;此 API 不保证跨 tab 或跨设备的权威配额。

通过 useFatigueState 执行操作会通知相同 key 的订阅者。useFatigue() 返回原始实例,直接调用它不会自动通知 React。tryConsume 允许时已经记账,应在接近实际展示的位置调用。

此入口使用浏览器 API,不能在服务端执行。SSR 应使用请求级状态,不要在模块作用域共享用户专属实例。参见 SSR 与水合指南。