message: reimplement useRecognizers based on useMemo
diff: @@ -27,51 +27,43 @@ export default function useRecognizers<Config extends Partial<GenericOptions>>(
  config: InternalConfig,
  nativeHandlers?: NativeHandlersPartial
  ): (...args: any[]) => HookReturnType<Config> {
  - const controller = React.useRef<Controller>() // The gesture controller keeping track of all gesture states
  - const nativeRefs = React.useRef<NativeHandlersPartial>()
  - if (!controller.current) {
  - // We only initialize the gesture controller once
  - controller.current = new Controller()
  - }
  -
  - // We reassign the config and handlers to the controller on every render.
  - controller.current!.config = config
  - controller.current!.handlers = handlers
  -
  - /**
  - * We also assign nativeHandlers to a ref, otherwise it they won't be refreshed
  - * on the next render.
  - */
  - nativeRefs.current = nativeHandlers
  -
  - /**
  - * When the component unmounts, we run the controller clean functions that will be responsible
  - * for removing listeners, clearing timeouts etc.
  - */
  - React.useEffect(() => controller.current!.clean, [])
  + // The gesture controller keeping track of all gesture states
  + const controller = React.useMemo(() => {
  + const current = new Controller();
  /**
  * The bind function will create gesture recognizers and return the right
  * bind object depending on whether `domTarget` was specified in the config object.
  */
  - const [bind] = React.useState(() => (...args: any[]) => {
  - controller.current!.resetBindings()
  + const bind = (...args: any[]) => {
  + current.resetBindings()
  classes.forEach(RecognizerClass => {
  - const recognizer = new RecognizerClass(controller.current!, args)
  - recognizer.addBindings()
  + new RecognizerClass(current, args).addBindings()
  })
  - if (nativeRefs.current) {
  + if (controller.nativeRefs) {
  // we also add event bindings for native handlers
  - Object.entries(nativeRefs.current).forEach(([eventName, fn]) => {
  + Object.entries(controller.nativeRefs).forEach(([eventName, fn]) => {
  // we're cheating when it comes to event type :(
  - controller.current!.addBindings(eventName as ReactEventHandlerKey, fn as Fn)
  + current.addBindings(eventName as ReactEventHandlerKey, fn as Fn)
  })
  }
  - return controller.current!.getBind() as HookReturnType<Config>
  - })
  + return current.getBind() as HookReturnType<Config>
  + }
  +
  + return ({ nativeRefs: nativeHandlers, current, bind })
  + }, []);
  +
  + // We reassign the config and handlers to the controller on every render.
  + controller.current!.config = config
  + controller.current!.handlers = handlers
  + // We assign nativeHandlers, otherwise they won't be refreshed on the next render.
  + controller.nativeRefs = nativeHandlers
  +
  + // Run controller clean functions on unmount.
  + React.useEffect(() => controller.current!.clean, [])
  - return bind
  + return controller.bind
  }
  