nowaalex / af-utils

Simple open-source tools that just work (usually fast)
https://af-utils.com
MIT License
75 stars 5 forks source link

@af-utils/scrollend-polyfill cannot use in React18 #37

Closed Ge-yuan-jun closed 6 months ago

Ge-yuan-jun commented 6 months ago

the npm package @af-utils/scrollend-polyfill cannot use in React18 when addEventListener to ref

  useEffect(() => {
    const scrollendCb = () => {
      console.log('scrollend trigger');
    };
    myRef?.current?.addEventListener('scrollend', scrollendCb);

    return myRef?.current?.removeEventListener('scrollend', scrollendCb);
  }, []);
if (arguments[0] === SCROLLEND_EVENT) {
    fn.apply(this, arguments as any);
}

the arguments[0] equals to react-scroll,not scrollend

nowaalex commented 6 months ago

You already managed to solve it?

Ge-yuan-jun commented 6 months ago

Not yet, I'm trying. May you provide some suggestions ?

nowaalex commented 6 months ago

I need to investigate this, will do this approximately in 1hr, could you please provide some additional information like:

Ge-yuan-jun commented 6 months ago

I use the pkg in webview. I already debug the code.

I have bind scroll & touchend in the jsx

when i comment the onScroll & onTouchEnd, the scrollend still cannot be triggered

<div
        id="container"
        ref={myRef}
        onScroll={onScroll}
        onTouchEnd={handleTouchEnd}
      >

the blow code has triggered twice when the page init

const patchScrollEnd = <T extends ListenerMethod>(
    objects: readonly PolyfilledTarget[],
    method: T,
    fn: (
      this: PolyfilledTarget,
      type: string,
      listener: PossibleListenerType,
      options?: AddEventListenerOptions
    ) => void
  ) =>
    objects.forEach(object => {
      const originalMethod = object[method];

      object[method] = function () {
        originalMethod.apply(this, arguments as any);
        if (arguments[0] === SCROLLEND_EVENT) {
          // the blow code has triggered when the page init
          console.log('patchScrollEnd trigger');
          fn.apply(this, arguments as any);
        }
      };
    });

but, the code blow cannot be triggered

addEventListener(
    'touchend',
    e => {
      for (const touch of e.changedTouches) {
        if (pointers.delete(touch.identifier) && lastTarget && !pointers.size) {
          // // the blow code cannot be triggered when I touchend
          console.log('touchend dispatch');
          dispatchScrollEvent(lastTarget);
          lastTarget = null;
        }
      }
    },
    { passive: true }
  );
Ge-yuan-jun commented 6 months ago

the touchend callback cannot be triggered because the lastTarget always be null

addEventListener(
    'touchend',
    e => {
      for (const touch of e.changedTouches) {
        // the lastTarget always be null
        if (pointers.delete(touch.identifier) && **lastTarget** && !pointers.size) {
          dispatchScrollEvent(lastTarget);
          lastTarget = null;
        }
      }
    },
    { passive: true }
  );
Ge-yuan-jun commented 6 months ago

emmm, this is a stupid issue.

I already solve it.

@nowaalex

useEffect(() => {
    myRef?.current?.addEventListener('scrollend', scrollendCb);
    // it should return function
    return () => myRef?.current?.removeEventListener('scrollend', scrollendCb);
  }, []);
nowaalex commented 6 months ago

Added example for this polyfill, so you could always try it online now https://af-utils.vercel.app/scrollend-polyfill/examples/react

nowaalex commented 6 months ago

Feel free to reopen this issue if you see something does not work. In order to improve debugging experience you could fork Stackblitz / Codesandbox examples which could be found here