Tour never starts when `run` is `true` from mount and `steps` are populated asynchronously
Describe the bug
When run is true from the very first render but steps is initially empty and populated later (e.g. fetched asynchronously), the tour silently never starts. It gets stuck at status: ready and no beacon/tooltip ever renders.
Steps to reproduce
function App() {
const [steps, setSteps] = useState([]);
useEffect(() => {
fetchSteps().then(setSteps); // arrive after mount
}, []);
// run is hard-coded true from the first render
return <Joyride run continuous steps={steps} />;
}Expected: once steps is non-empty, the tour starts (status: running, tour:start fires).
Actual: the store goes idle → ready and stops there; the tour never runs.
Root cause
controls.start() is only invoked in two places: the mount effect (run && size, which is false at mount because steps is empty) and usePropSync when run changes to truthy (which never happens here, because run was already true). The useUpdateEffect in useTourEngine that handles steps-arriving-after-mount only transitions the store to ready, never to running:
useUpdateEffect(() => {
if (run && size && status === STATUS.IDLE) {
store.current.updateState({ status: STATUS.READY }); // stops at ready
}
}, [run, size, status]);react-joyride version
3.2.0
Reproduction link
No response
Screenshots or videos
No response
Additional context
The common pattern run={steps.length > 0} works, because there run transitions false → true and goes through usePropSync. Only the "run hard-coded true + async steps" combination is affected.
Source: gilbarbara/react-joyride