react-joyride

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

React Joyride v3

React Joyride v3

Create guided tours in React apps. Two public APIs: the
useJoyride()
hook (recommended) and the
<Joyride>
component.
用于在React应用中创建引导式导览。提供两个公开API:
useJoyride()
hook(推荐使用)和
<Joyride>
组件。

Quick Start

快速开始

Using the hook (recommended)

使用hook(推荐)

tsx
import { useJoyride, STATUS, Status } from 'react-joyride';

function App() {
  const { Tour } = useJoyride({
    continuous: true,
    run: true,
    steps: [
      { target: '.my-element', content: 'This is the first step', title: 'Welcome' },
      { target: '#sidebar', content: 'Navigate here', placement: 'right' },
    ],
    onEvent: (data) => {
      if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
        // Tour ended
      }
    },
  });

  return <div>{Tour}{/* rest of app */}</div>;
}
tsx
import { useJoyride, STATUS, Status } from 'react-joyride';

function App() {
  const { Tour } = useJoyride({
    continuous: true,
    run: true,
    steps: [
      { target: '.my-element', content: 'This is the first step', title: 'Welcome' },
      { target: '#sidebar', content: 'Navigate here', placement: 'right' },
    ],
    onEvent: (data) => {
      if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
        // Tour ended
      }
    },
  });

  return <div>{Tour}{/* rest of app */}</div>;
}

Using the component

使用组件

tsx
import { Joyride, STATUS, Status } from 'react-joyride';

function App() {
  return (
    <Joyride
      continuous
      run={true}
      steps={[
        { target: '.my-element', content: 'First step' },
        { target: '#sidebar', content: 'Second step' },
      ]}
      onEvent={(data) => {
        if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
          // Tour ended
        }
      }}
    />
  );
}
The hook returns
{ controls, failures, on, state, step, Tour }
. Render
Tour
in your JSX.
tsx
import { Joyride, STATUS, Status } from 'react-joyride';

function App() {
  return (
    <Joyride
      continuous
      run={true}
      steps={[
        { target: '.my-element', content: 'First step' },
        { target: '#sidebar', content: 'Second step' },
      ]}
      onEvent={(data) => {
        if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
          // Tour ended
        }
      }}
    />
  );
}
hook返回值包含
{ controls, failures, on, state, step, Tour }
,你需要在JSX中渲染
Tour
组件。

Core Concepts

核心概念

The tour has two state dimensions:
Tour Status:
idle -> ready -> waiting -> running <-> paused -> finished | skipped
  • idle
    : No steps loaded
  • ready
    : Steps loaded, waiting for
    run: true
  • waiting
    :
    run=true
    but steps loading async (transitions to running when steps arrive)
  • running
    : Tour active
  • paused
    : Tour paused (controlled mode at COMPLETE, or
    stop()
    called)
  • finished
    /
    skipped
    : Tour ended
Step Lifecycle (per step):
init -> ready -> beacon_before -> beacon -> tooltip_before -> tooltip -> complete
  • *_before
    phases: scrolling and positioning happen here
  • beacon
    : Pulsing indicator shown (skipped when
    continuous
    + navigating,
    skipBeacon
    , or
    placement: 'center'
    )
  • tooltip
    : The tooltip is visible and interactive
导览包含两个状态维度:
导览状态
idle -> ready -> waiting -> running <-> paused -> finished | skipped
  • idle
    :没有加载任何步骤
  • ready
    :步骤加载完成,等待
    run: true
    触发
  • waiting
    run=true
    但步骤正在异步加载,步骤加载完成后会切换到running状态
  • running
    :导览正在运行
  • paused
    :导览已暂停(受控模式下步骤完成时,或是调用了
    stop()
    方法)
  • finished
    /
    skipped
    :导览已结束
步骤生命周期(每个步骤单独执行):
init -> ready -> beacon_before -> beacon -> tooltip_before -> tooltip -> complete
  • *_before
    阶段:会在这个阶段执行滚动和定位操作
  • beacon
    :展示脉冲指示器(如果开启
    continuous
    且正在跳转步骤、设置了
    skipBeacon
    ,或是
    placement: 'center'
    时会跳过该阶段)
  • tooltip
    :工具提示可见且可交互

Step Configuration

步骤配置

Each step requires
target
and
content
. All other fields are optional.
tsx
{
  target: '.my-element',       // CSS selector, HTMLElement, React ref, or () => HTMLElement
  content: 'Step body text',   // ReactNode
  title: 'Optional title',    // ReactNode
  placement: 'bottom',        // Default. Also: top, left, right, *-start, *-end, auto, center
  id: 'unique-id',            // Optional identifier
  data: { custom: 'data' },   // Attached to event callbacks
}
每个步骤都需要设置
target
content
,其余字段都是可选的。
tsx
{
  target: '.my-element',       // CSS选择器、HTMLElement、React ref,或是返回HTMLElement的函数
  content: 'Step body text',   // ReactNode类型
  title: 'Optional title',    // ReactNode类型
  placement: 'bottom',        // 默认值,可选值:top、left、right、*-start、*-end、auto、center
  id: 'unique-id',            // 可选标识符
  data: { custom: 'data' },   // 挂载到事件回调上的自定义数据
}

Target types

Target类型

tsx
// CSS selector
{ target: '.sidebar-nav' }
// HTMLElement
{ target: document.getElementById('my-el') }
// React ref
const ref = useRef(null);
{ target: ref }
// Function (evaluated each lifecycle)
{ target: () => document.querySelector('.dynamic-element') }
tsx
// CSS选择器
{ target: '.sidebar-nav' }
// HTMLElement
{ target: document.getElementById('my-el') }
// React ref
const ref = useRef(null);
{ target: ref }
// 函数(每次生命周期执行时都会重新计算)
{ target: () => document.querySelector('.dynamic-element') }

Common step options (override per-step)

常用步骤配置项(可按步骤单独覆盖全局配置)

OptionDefaultDescription
placement
'bottom'
Tooltip position. Use
'center'
for modal-style (requires
target: 'body'
)
skipBeacon
false
Skip beacon, show tooltip directly
buttons
['back','close','primary']
Buttons in tooltip. Add
'skip'
for skip button
hideOverlay
false
Don't show dark overlay
blockTargetInteraction
false
Block clicks on highlighted element
before
-
(data) => Promise<void>
— async hook before step shows
after
-
(data) => void
— fire-and-forget hook after step completes
skipScroll
false
Don't scroll to target
scrollTarget
-Scroll to this element instead of
target
spotlightTarget
-Highlight this element instead of
target
spotlightPadding
10
Padding around spotlight. Number or
{ top, right, bottom, left }
targetWaitTimeout
1000
ms to wait for target to appear.
0
= no waiting
beforeTimeout
5000
ms to wait for
before
hook.
0
= no timeout
All
Options
fields can be set globally via
options
prop or per-step. Per-step values override global.
配置项默认值说明
placement
'bottom'
工具提示位置,设置
'center'
可实现模态框样式的导览(需要搭配
target: 'body'
使用)
skipBeacon
false
跳过beacon展示,直接显示工具提示
buttons
['back','close','primary']
工具提示内的按钮,添加
'skip'
可展示跳过按钮
hideOverlay
false
不展示深色背景遮罩
blockTargetInteraction
false
阻止用户点击高亮的目标元素
before
-
(data) => Promise<void>
— 步骤展示前执行的异步钩子,导览会等待Promise resolve后再展示步骤
after
-
(data) => void
— 步骤完成后执行的异步钩子,无需等待执行完成
skipScroll
false
不自动滚动到目标元素位置
scrollTarget
-滚动到该元素而非
target
指定的元素
spotlightTarget
-高亮该元素而非
target
指定的元素
spotlightPadding
10
高亮区域的内边距,可传入数字或是
{ top, right, bottom, left }
格式的对象
targetWaitTimeout
1000
等待目标元素出现的毫秒数,设置
0
表示不等待
beforeTimeout
5000
等待
before
钩子执行完成的毫秒数,设置
0
表示不设超时
所有配置项都可以通过
options
prop全局设置,或是按步骤单独设置,单步设置的优先级高于全局配置。

Uncontrolled vs Controlled

非受控模式 vs 受控模式

Uncontrolled (default — strongly preferred)

非受控模式(默认,强烈推荐)

The tour manages step navigation internally. This is the right choice for most use cases.
The library handles async transitions for you. If a step needs to wait for a UI change (dropdown opening, data loading, animation), use
before
hooks — the tour waits for the promise to resolve before showing the step. If a target element isn't in the DOM yet,
targetWaitTimeout
(default: 1000ms) handles polling for it. You do NOT need controlled mode for these cases.
tsx
const { Tour } = useJoyride({
  continuous: true,
  run: isRunning,
  steps: [
    { target: '.nav', content: 'Navigation' },
    {
      target: '.dropdown-item',
      content: 'Inside the dropdown',
      before: () => {
        // Open dropdown and wait for animation — tour waits automatically
        openDropdown();
        return new Promise(resolve => setTimeout(resolve, 300));
      },
      after: () => closeDropdown(), // Clean up after step (fire-and-forget)
    },
    { target: '.main-content', content: 'Main content' },
  ],
  onEvent: (data) => {
    if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
      setIsRunning(false);
    }
  },
});
导览内部自动管理步骤跳转,绝大多数场景下都是最优选择。
库会自动处理异步过渡。如果某个步骤需要等待UI变化(比如下拉框展开、数据加载、动画执行),可以使用
before
钩子,导览会自动等待Promise resolve后再展示步骤。如果目标元素还没有挂载到DOM上,
targetWaitTimeout
(默认1000ms)会自动轮询查找目标元素,这些场景你都不需要使用受控模式。
tsx
const { Tour } = useJoyride({
  continuous: true,
  run: isRunning,
  steps: [
    { target: '.nav', content: 'Navigation' },
    {
      target: '.dropdown-item',
      content: 'Inside the dropdown',
      before: () => {
        // 展开下拉框并等待动画执行完成,导览会自动等待
        openDropdown();
        return new Promise(resolve => setTimeout(resolve, 300));
      },
      after: () => closeDropdown(), // 步骤完成后清理,无需等待执行完成
    },
    { target: '.main-content', content: 'Main content' },
  ],
  onEvent: (data) => {
    if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
      setIsRunning(false);
    }
  },
});

Controlled (with
stepIndex
) — use sparingly

受控模式(搭配
stepIndex
使用):谨慎使用

Only use controlled mode when the parent genuinely needs to manage the step index externally (e.g., syncing with URL params, external state machines, or complex multi-component coordination that
before
/
after
hooks can't handle).
tsx
const [stepIndex, setStepIndex] = useState(0);
const [run, setRun] = useState(true);

const { Tour } = useJoyride({
  continuous: true,
  run,
  stepIndex,  // This makes it controlled
  steps,
  onEvent: (data) => {
    const { action, index, status, type } = data;

    if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(status)) {
      setRun(false);
      return;
    }

    if (type === 'step:after' || type === 'error:target_not_found') {
      setStepIndex(index + (action === 'prev' ? -1 : 1));
    }
  },
});
Controlled mode rules:
  • go()
    and
    reset()
    are disabled (logged warning)
  • You must update
    stepIndex
    in response to events
  • The tour pauses at COMPLETE — you must advance it
  • Prefer uncontrolled mode with
    before
    /
    after
    hooks unless you have a strong reason for external index management
仅当父组件确实需要外部管理步骤索引时才使用受控模式(比如和URL参数同步、对接外部状态机,或是
before
/
after
钩子无法满足的复杂多组件协同场景)。
tsx
const [stepIndex, setStepIndex] = useState(0);
const [run, setRun] = useState(true);

const { Tour } = useJoyride({
  continuous: true,
  run,
  stepIndex,  // 该配置项会开启受控模式
  steps,
  onEvent: (data) => {
    const { action, index, status, type } = data;

    if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(status)) {
      setRun(false);
      return;
    }

    if (type === 'step:after' || type === 'error:target_not_found') {
      setStepIndex(index + (action === 'prev' ? -1 : 1));
    }
  },
});
受控模式使用规则:
  • go()
    reset()
    方法会被禁用(会输出警告日志)
  • 你必须在事件回调中主动更新
    stepIndex
  • 导览会在步骤完成时暂停,你必须主动推进步骤
  • 除非你有明确的外部管理索引的需求,否则优先使用搭配
    before
    /
    after
    钩子的非受控模式

Event System

事件系统

onEvent
callback

onEvent
回调

tsx
onEvent: (data: EventData, controls: Controls) => void
The
data
object contains the full tour state plus event-specific fields. The
controls
object lets you programmatically control the tour.
tsx
onEvent: (data: EventData, controls: Controls) => void
data
对象包含完整的导览状态和事件专属字段,
controls
对象可以让你通过代码控制导览行为。

Event types (in order per step)

事件类型(按每个步骤的触发顺序排列)

EventWhen
tour:start
Tour begins
step:before_hook
before
hook is called
step:before
Target found, step about to render
scroll:start
Scrolling to target
scroll:end
Scroll complete
beacon
Beacon shown
tooltip
Tooltip shown
step:after
User navigated (next/prev/close/skip)
step:after_hook
after
hook called
tour:end
Tour finished or skipped
tour:status
Status changed (on stop/reset)
error:target_not_found
Target element not found
error
Generic error
事件触发时机
tour:start
导览开始时
step:before_hook
before
钩子被调用时
step:before
找到目标元素,即将渲染步骤时
scroll:start
开始滚动到目标元素时
scroll:end
滚动完成时
beacon
beacon展示时
tooltip
工具提示展示时
step:after
用户触发跳转(下一步/上一步/关闭/跳过)时
step:after_hook
after
钩子被调用时
tour:end
导览完成或被跳过时
tour:status
导览状态变化时(调用stop/reset时触发)
error:target_not_found
找不到目标元素时
error
通用错误触发时

Event subscription with
on()

使用
on()
订阅事件

tsx
const { on, Tour } = useJoyride({ ... });

useEffect(() => {
  const unsubscribe = on('tooltip', (data, controls) => {
    analytics.track('tour_step_viewed', { step: data.index });
  });
  return unsubscribe;
}, [on]);
tsx
const { on, Tour } = useJoyride({ ... });

useEffect(() => {
  const unsubscribe = on('tooltip', (data, controls) => {
    analytics.track('tour_step_viewed', { step: data.index });
  });
  return unsubscribe;
}, [on]);

Controls

控制方法

Available via
useJoyride()
return value or
onEvent
second argument:
MethodDescription
next()
Advance to next step
prev()
Go to previous step
close(origin?)
Close current step, advance
skip(origin?)
Skip the tour entirely
start(index?)
Start the tour
stop(advance?)
Stop (pause) the tour
go(index)
Jump to step (uncontrolled only)
reset(restart?)
Reset tour (uncontrolled only)
open()
Open tooltip for current step
info()
Get current state
可以通过
useJoyride()
的返回值或是
onEvent
的第二个参数获取控制方法:
方法说明
next()
前进到下一步
prev()
回退到上一步
close(origin?)
关闭当前步骤,继续推进导览
skip(origin?)
直接跳过整个导览
start(index?)
启动导览
stop(advance?)
停止(暂停)导览
go(index)
跳转到指定步骤(仅非受控模式可用)
reset(restart?)
重置导览(仅非受控模式可用)
open()
打开当前步骤的工具提示
info()
获取当前导览状态

Styling & Theming

样式与主题

Three layers of customization (from simple to full control):
提供三层自定义能力(从简单到完全可控):

1. Color options (simplest)

1. 颜色配置(最简单)

tsx
options: {
  primaryColor: '#1976d2',      // Buttons and beacon
  backgroundColor: '#1a1a2e',   // Tooltip background
  textColor: '#ffffff',         // Tooltip text
  overlayColor: 'rgba(0,0,0,0.7)', // Overlay backdrop
  arrowColor: '#1a1a2e',        // Arrow (match background)
}
tsx
options: {
  primaryColor: '#1976d2',      // 按钮和beacon的颜色
  backgroundColor: '#1a1a2e',   // 工具提示背景色
  textColor: '#ffffff',         // 工具提示文字颜色
  overlayColor: 'rgba(0,0,0,0.7)', // 背景遮罩颜色
  arrowColor: '#1a1a2e',        // 箭头颜色(建议和背景色保持一致)
}

2. Styles override

2. 样式覆盖

tsx
styles: {
  tooltip: { borderRadius: 12 },
  buttonPrimary: { backgroundColor: '#1976d2' },
  buttonBack: { color: '#666' },
  spotlight: { borderRadius: 8 },
}
Style keys:
arrow
,
beacon
,
beaconInner
,
beaconOuter
,
beaconWrapper
,
buttonBack
,
buttonClose
,
buttonPrimary
,
buttonSkip
,
floater
,
loader
,
overlay
,
tooltip
,
tooltipContainer
,
tooltipContent
,
tooltipFooter
,
tooltipFooterSpacer
,
tooltipTitle
tsx
styles: {
  tooltip: { borderRadius: 12 },
  buttonPrimary: { backgroundColor: '#1976d2' },
  buttonBack: { color: '#666' },
  spotlight: { borderRadius: 8 },
}
可配置的样式key:
arrow
,
beacon
,
beaconInner
,
beaconOuter
,
beaconWrapper
,
buttonBack
,
buttonClose
,
buttonPrimary
,
buttonSkip
,
floater
,
loader
,
overlay
,
tooltip
,
tooltipContainer
,
tooltipContent
,
tooltipFooter
,
tooltipFooterSpacer
,
tooltipTitle

3. Custom components (full control)

3. 自定义组件(完全可控)

Custom Components

自定义组件

Replace any UI component via props. Each receives render props with step data and button handlers.
可以通过prop替换任意UI组件,每个组件都会收到包含步骤数据和按钮处理函数的render prop。

Custom Tooltip

自定义工具提示

tsx
import type { TooltipRenderProps } from 'react-joyride';

function MyTooltip({ backProps, index, primaryProps, size, skipProps, step, tooltipProps }: TooltipRenderProps) {
  return (
    <div {...tooltipProps} style={{ background: '#fff', padding: 16, borderRadius: 8, width: step.width }}>
      {step.title && <h3>{step.title}</h3>}
      <div>{step.content}</div>
      <div>
        {index > 0 && <button {...backProps}>Back</button>}
        <button {...primaryProps}>Next</button>
      </div>
    </div>
  );
}

// Usage
<Joyride tooltipComponent={MyTooltip} ... />
Important: Spread
tooltipProps
on the container (sets
role="dialog"
and
aria-modal
). Spread button props (
backProps
,
primaryProps
,
closeProps
,
skipProps
) on buttons for correct action handling.
tsx
import type { TooltipRenderProps } from 'react-joyride';

function MyTooltip({ backProps, index, primaryProps, size, skipProps, step, tooltipProps }: TooltipRenderProps) {
  return (
    <div {...tooltipProps} style={{ background: '#fff', padding: 16, borderRadius: 8, width: step.width }}>
      {step.title && <h3>{step.title}</h3>}
      <div>{step.content}</div>
      <div>
        {index > 0 && <button {...backProps}>Back</button>}
        <button {...primaryProps}>Next</button>
      </div>
    </div>
  );
}

// 使用方式
<Joyride tooltipComponent={MyTooltip} ... />
重要提示:将
tooltipProps
展开到容器元素上(会自动设置
role="dialog"
aria-modal
属性),将按钮相关prop(
backProps
,
primaryProps
,
closeProps
,
skipProps
)展开到对应按钮上,保证事件处理逻辑正常生效。

Custom Beacon

自定义Beacon

Must render a
<span>
(placed inside a
<button>
wrapper). Receives
BeaconRenderProps
:
{ continuous, index, isLastStep, size, step }
.
必须渲染一个
<span>
(会被包裹在
<button>
容器内),接收的
BeaconRenderProps
参数:
{ continuous, index, isLastStep, size, step }

Custom Arrow

自定义箭头

Receives
ArrowRenderProps
:
{ base, placement, size }
.
接收的
ArrowRenderProps
参数:
{ base, placement, size }

Custom Loader

自定义加载器

Receives
LoaderRenderProps
:
{ step }
. Set to
null
to disable the loader.
接收的
LoaderRenderProps
参数:
{ step }
,设置为
null
可禁用加载器。

Problem → Solution Guide

问题解决方案指南

I need to...Use
Wait for async UI changes between steps (dropdown, animation, data load)
before
hook returning a Promise — not controlled mode
Control step navigation externally (URL sync, external state machine)Controlled mode with
stepIndex
— but try
before
/
after
hooks first
Track which steps failed (target missing, hook error)
failures
array from
useJoyride()
return
Listen to specific events without
onEvent
switch
on('event:type', handler)
from
useJoyride()
return
Show a centered modal-style step
target: 'body'
+
placement: 'center'
需求实现方案
在步骤之间等待异步UI变化(下拉框、动画、数据加载)使用返回Promise的
before
钩子,不需要使用受控模式
外部控制步骤跳转(URL同步、外部状态机)使用搭配
stepIndex
的受控模式,但请先尝试
before
/
after
钩子是否能满足需求
追踪哪些步骤执行失败(目标缺失、钩子错误)使用
useJoyride()
返回的
failures
数组
不需要通过
onEvent
分支判断,直接监听特定事件
使用
useJoyride()
返回的
on('event:type', handler)
方法
展示居中的模态框样式步骤搭配
target: 'body'
placement: 'center'
使用

Common Gotchas & Debugging

常见问题与调试

Use
debug: true
first

优先使用
debug: true

The
debug
prop is the most powerful troubleshooting tool. It logs detailed lifecycle transitions, state changes, and event emissions to the console. Always start here when something isn't working.
tsx
<Joyride debug={true} ... />
// or
useJoyride({ debug: true, ... })
The console output shows exactly which lifecycle phase the tour reaches, what actions are firing, and where it gets stuck.
debug
prop是最强大的排障工具,它会在控制台输出详细的生命周期流转、状态变化和事件触发日志。当出现异常时请优先开启该配置。
tsx
<Joyride debug={true} ... />
// 或是
useJoyride({ debug: true, ... })
控制台输出会清晰展示导览运行到了哪个生命周期阶段、触发了哪些操作、卡在哪一个环节。

Tour not starting

导览没有启动

  • Check
    run={true}
    is set
  • Verify
    steps
    array is not empty and steps have valid
    target
    +
    content
  • For SSR: use
    <Joyride>
    component (auto-guards DOM access) or check
    typeof window !== 'undefined'
  • 检查是否设置了
    run={true}
  • 确认
    steps
    数组不为空,且每个步骤都包含有效的
    target
    content
  • 服务端渲染场景:使用
    <Joyride>
    组件(会自动处理DOM访问的安全判断),或是手动判断
    typeof window !== 'undefined'

Target not found

找不到目标元素

  • Test selector in console:
    document.querySelector('.your-selector')
  • Element must be visible (not
    display: none
    ,
    visibility: hidden
    , or zero dimensions)
  • If element mounts later, increase
    targetWaitTimeout
    (default: 1000ms)
  • Set
    targetWaitTimeout: 0
    to skip waiting entirely
  • In uncontrolled mode, missing targets auto-advance; in controlled mode, handle
    error:target_not_found
    event
  • 在控制台测试选择器是否有效:
    document.querySelector('.your-selector')
  • 元素必须是可见的(不能是
    display: none
    visibility: hidden
    ,或是宽高为0)
  • 如果元素是后挂载的,可以增大
    targetWaitTimeout
    (默认1000ms)
  • 设置
    targetWaitTimeout: 0
    可以完全跳过等待
  • 非受控模式下,缺失的目标会自动跳过并推进到下一步;受控模式下需要手动处理
    error:target_not_found
    事件

Tooltip never appears / overlay flashes

工具提示始终不显示 / 遮罩闪烁

  • Add
    debug: true
    and check the console to see which lifecycle phase is reached
  • Verify the target element is in the viewport or scrollable
  • Check for CSS
    overflow: hidden
    on ancestors clipping the target
  • If using portals or modals, the target may not be accessible
  • 开启
    debug: true
    ,查看控制台输出确认导览运行到了哪个生命周期阶段
  • 确认目标元素在视口内或是可滚动到可见区域
  • 检查祖先元素是否设置了
    overflow: hidden
    裁剪了目标元素
  • 如果使用了portal或是模态框,可能目标元素无法被正常访问

Controlled mode stuck

受控模式卡住

  • First question: do you actually need controlled mode? Most async needs are solved with
    before
    /
    after
    hooks in uncontrolled mode
  • If controlled: you MUST update
    stepIndex
    in your
    onEvent
    handler when
    type === 'step:after'
  • Handle both forward (
    action !== 'prev'
    ) and backward (
    action === 'prev'
    ) navigation
  • Also handle
    error:target_not_found
    to skip broken steps
  • go()
    and
    reset()
    don't work in controlled mode
  • 首先确认你是否真的需要受控模式,绝大多数异步需求都可以通过非受控模式的
    before
    /
    after
    钩子解决
  • 如果确实使用受控模式:你必须在
    onEvent
    回调中监听
    type === 'step:after'
    事件,并主动更新
    stepIndex
  • 同时处理向前(
    action !== 'prev'
    )和向后(
    action === 'prev'
    )的跳转逻辑
  • 也要处理
    error:target_not_found
    事件跳过异常步骤
  • 受控模式下
    go()
    reset()
    方法不会生效

Before hook timeout

Before钩子超时

  • Default
    beforeTimeout
    is 5000ms — increase if your async operation takes longer
  • Set
    beforeTimeout: 0
    for no timeout
  • The loader appears after
    loaderDelay
    (300ms) while waiting
  • 默认
    beforeTimeout
    是5000ms,如果你的异步操作耗时更长可以增大该值
  • 设置
    beforeTimeout: 0
    可以不设置超时
  • 等待过程中加载器会在
    loaderDelay
    (默认300ms)后展示

Scroll issues

滚动异常

  • Use
    scrollTarget
    to scroll to a different element than the tooltip target
  • Adjust
    scrollOffset
    (default: 20px) for headers or fixed elements
  • Set
    skipScroll: true
    to disable auto-scrolling for a step
  • scrollToFirstStep: false
    by default — set to
    true
    if first step is off-screen
  • 使用
    scrollTarget
    配置滚动到和工具提示目标不同的元素
  • 调整
    scrollOffset
    (默认20px)适配固定头部或固定元素
  • 针对单个步骤设置
    skipScroll: true
    禁用自动滚动
  • 默认
    scrollToFirstStep: false
    ,如果第一个步骤不在视口内可以设置为
    true

Center placement

居中布局

  • Use
    placement: 'center'
    with
    target: 'body'
    for modal-style centered tooltips
  • Center placement automatically hides the beacon and arrow
  • 搭配
    target: 'body'
    placement: 'center'
    实现模态框样式的居中工具提示
  • 居中布局会自动隐藏beacon和箭头

Imports

导入说明

tsx
// Named exports only (no default export in v3)
import { Joyride, useJoyride } from 'react-joyride';

// Constants for type-safe comparisons
import { ACTIONS, EVENTS, LIFECYCLE, ORIGIN, STATUS } from 'react-joyride';

// Types
import type { Step, Props, EventData, Controls, TooltipRenderProps } from 'react-joyride';
tsx
// v3仅支持命名导出,没有默认导出
import { Joyride, useJoyride } from 'react-joyride';

// 类型安全对比用的常量
import { ACTIONS, EVENTS, LIFECYCLE, ORIGIN, STATUS } from 'react-joyride';

// 类型定义
import type { Step, Props, EventData, Controls, TooltipRenderProps } from 'react-joyride';

Reference Files

参考文件

Read these for complete API details:
  • references/api-props-options.md
    — Full Props, Options (all 30+ fields with defaults), Locale, FloatingOptions, Styles types
  • references/api-step-state-controls.md
    — Step, StepMerged, StepTarget, State, Controls (all 10 methods), UseJoyrideReturn, StepFailure
  • references/api-events-components.md
    — All 13 event types, ACTIONS/LIFECYCLE/STATUS/ORIGIN constants, EventData, custom component render props
  • references/patterns.md
    — Complete working examples: controlled mode, before/after hooks, custom tooltip, event subscription, dynamic steps
阅读以下文件获取完整API详情:
  • references/api-props-options.md
    — 完整Props、Options(所有30+字段及默认值)、Locale、FloatingOptions、Styles类型定义
  • references/api-step-state-controls.md
    — Step、StepMerged、StepTarget、State、Controls(所有10个方法)、UseJoyrideReturn、StepFailure类型定义
  • references/api-events-components.md
    — 所有13种事件类型、ACTIONS/LIFECYCLE/STATUS/ORIGIN常量、EventData、自定义组件render prop定义
  • references/patterns.md
    — 完整可运行示例:受控模式、before/after钩子、自定义工具提示、事件订阅、动态步骤