I have a form with a meeting booking inside it. Part of this is a calendar component, that has a fairly complex UI.
<Calendar fullName={fullName} email={email} onEventScheduled={onEventScheduled} />
This works fine.
As React users will know, react re-renders the form when any of the inputs change. As the calendar is only dependent on some of the inputs (fullName
, email
and onEventScheduled
), but not others, and is slow to draw, I'd like to use useMemo()
to stop the calendar re-rendering:
(updated to use JSX per @dmitryguzeev comment)
const MemoizedCalendar = useMemo(() => {
return <Calendar fullName={fullName} email={email} onEventScheduled={onEventScheduled} />;
}, [email, fullName, onEventScheduled]);
And then later
<MemoizedCalendar fullName={fullName} email={email} onEventScheduled={onEventScheduled} />
However swapping to MemoizedCalendar gives the following error:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `Formik`.
(I happen to be using Formik, however the component works fine with Calendar
per above, just MemoizedCalendar
fails)
Edit: I've also tried useCallback()
after reading this article on UseMemo()
It is worth saying that if a component receives a function as a prop, you need to use the useCallback hook, so that it only declares the function again when necessary. Otherwise props will be different every render, since the function prop will always have a new reference.
const MemoizedCalendar = useCallback(() => {
return Calendar(email, fullName, onEventScheduled);
}, [email, fullName, onEventScheduled]);
Which fixes the error, but still re-renders unnecessarily when items outside email
, fullName
, and onEventScheduled
are modified.
How can I memoize this hook component?
To memoize your component JSX tree parts using
useMemo
, you need to first render it separately inside ofuseMemo
:and then use it as a value rather than as a component in your JSX tree: