Antonio Erdeljac
Antonio Erdeljac

Reputation: 3244

React Hooks - Memoise functions without invoking them

I have a following function which I use to control my modals:

const getModalProps = useCallback(
(id) => ({
  onClose: () => handleClose(id),
  onOpen: () => handleOpen(id),
  isOpen: isOpen(id),
}),
[handleClose, handleOpen, isOpen],
);

The idea is to be used something like <Modal {...getModalProps('userModal')} />. Problem arrives when I want to use it in the following way:

const modalProps = getModalProps('userModal');

useEffect(() => { modalProps.onOpen() }, [modalProps.onOpen])

This causes an infinite loop, because modalProps.onOpen is actually an anonymous arrow function, instead of useCallback memoised function.

I am at loss of ideas as to how I can use getModalProps function which returns memoised, but not invoked functions of handleOpen and handleClose.

Something like this is the idea (I am aware this cannot work, just a concept):

const getModalProps = useCallback(
(id) => ({
  onClose: memoise(() => handleClose(id)),
  onOpen: memoise(() => handleOpen(id)),
  isOpen: isOpen(id),
}),
[handleClose, handleOpen, isOpen],
);

handleClose and handleOpen are just your normal useCallback functions.

Please leave a comment if more info is needed.

Upvotes: 2

Views: 180

Answers (1)

Ori Drori
Ori Drori

Reputation: 191976

Create a custom hook that create memoized onClose, and onOpen, and returns the modalProps object:

const useGetModalProps = id => { // you can also pass isOpen to the hook
  const onClose = useCallback(() => handleClose(id), [handleClose, id]);
  const onOpen = useCallback(() => handleOpen(id), [handleOpen, id]);

  return {
    onClose,
    onOpen,
    isOpen: isOpen(id),
  };
}

Usage:

const modalProps = useGetModalProps('userModal');

useEffect(() => { modalProps.onOpen() }, [modalProps.onOpen])

Or

<Modal {...modalProps } />

Upvotes: 3

Related Questions