webrix icon indicating copy to clipboard operation
webrix copied to clipboard

Use an internal ref to eliminate the need for `useMemo()`

Open ykadosh opened this issue 3 years ago • 3 comments

Currently, when using Movable.useMove() or Resizable.useResize(), you need to wrap the list of provided operations in a useMemo. We can eliminate the need for useMemo if we maintain the list of operation in a ref internally, and access the operations through the ref only.

ykadosh avatar Jun 11 '21 07:06 ykadosh

Following these instruction, we get the following solution:

export const useMove = ops => {
    const opsRef = useRef(ops);
    const shared = useRef({});

    const onBeginMove = useCallback(e => {
        opsRef.current.forEach(({onBeginMove}) => onBeginMove(e, shared.current));
    }, [opsRef]);

    ...

};

However, if we look at this use case from Scrollable\components\HorizontalScrollbar\HorizontalScrollbar.jsx: const props = Movable.useMove(useMemo(() => [move(container, thumb, track)], [container])); The ops prop can change. This is an issue because the value inside the hook won't change once we use useRef, meaning we will always use the initial value of ops.

gaeaehrlich avatar Feb 28 '22 09:02 gaeaehrlich

You need to keep the ref updated:

opsRef.current = ops;

We do this in various hooks, see this for example: https://github.com/open-amdocs/webrix/blob/master/src/hooks/useAnimationFrame/useAnimationFrame.js#L24

ykadosh avatar Feb 28 '22 14:02 ykadosh

Ok, I understand everything now, thanks for that example!

export const useMove = ops => {
    const shared = useRef({});
    const opsRef = useRef();
    opsRef.current = ops;

    const onBeginMove = useCallback(e => {
        opsRef.current.forEach(({onBeginMove}) => onBeginMove(e, shared.current));
    }, []);

    const onMove = useCallback(e => {
        opsRef.current.forEach(({onMove}) => onMove(e, shared.current));
    }, []);

    const onEndMove = useCallback(e => {
        opsRef.current.forEach(({onEndMove}) => onEndMove(e, shared.current))
    }, []);

    return {onBeginMove, onMove, onEndMove};
};

yairEO avatar Feb 28 '22 16:02 yairEO

Closed as part of PR https://github.com/open-amdocs/webrix/pull/85

yairEO avatar Jan 29 '23 18:01 yairEO