kamranahmedse / driver.js

A light-weight, no-dependency, vanilla JavaScript engine to drive user's focus across the page
https://driverjs.com
MIT License
22.66k stars 1.01k forks source link

[BUG] - React - When using multiple instances in the page/component, the last instance is always being used #505

Closed feri-irawan closed 3 months ago

feri-irawan commented 3 months ago

useDriver.ts

type Options = Config & {
  key: string // for localStorage
  start?: boolean
}

export function useDriver({
  key,
  start = true,
  ...options
}: Options) {

  const driverObj = useMemo(() => {
    return driver(options)
  }, [options])

  useEffect(() => {
    if (!start) return

    driverObj.drive()

    return () => driverObj.destroy()
  }, [start, driverObj])

  return driverObj
}

page.tsx

import { useDriver } from "./hooks/useDriver";
import { tour1 } from "./constants/tour1";
import { tour2 } from "./constants/tour2";

export default function Page() {
  const driver1 = useDriver({
    key: "tour-1",
    steps: tour1,
    start: true,
    startButtonSelector: "#start-tour-1",
  });

  const driver2 = useDriver({
    key: "tour-2",
    steps: tour2,
    start: true,
    startButtonSelector: "#start-tour-2",
  });

  return (
    <div>
      <button id="start-tour-1" onClick={() => driver1.drive()}>
        Start Tour 1
      </button>
      <button id="start-tour-2" onClick={() => driver2.drive()}>
        Start Tour 2
      </button>
    </div>
  );
}

Bug

  1. Click Start Tour 1 -> Tour 2 started!
  2. Then click Start Tour 1 -> Tour 2 started again!
feri-irawan commented 3 months ago

SOLVED!

Instead set the steps as options in driver() i am using driverObj.setSteps({})

const driverObj = useMemo(() => {
    return driver(options)
  }, [options])

const drive = useCallback(() => {
  driverObj.setSteps(steps)
  driverObj.drive()
}, [driverObj, steps])

return { ...driverObj, drive }