I am trying to figure out a way to be able to memoize React components by specifying particular props.
For instance, if you use React.memo
— it memoizes the component based on all props.
What I am trying to achieve is being able to pass particular props as a dependency to a util (say, SuperMemo
) and the component will be memoized based on those props. The approach is very similar to what recompose — compose the component before export.
Here's an example code
import React from "react";
const isFunction = value =>
value &&
(Object.prototype.toString.call(value) === "[object Function]" ||
"function" === typeof value ||
value instanceof Function);
export const memo = (Comp, resolver) => {
if (isFunction(resolver)) {
const Memoized = props => {
const deps = resolver(props);
if (deps && deps.length) {
// eslint-disable-next-line react-hooks/rules-of-hooks
return React.useCallback(React.createElement(Comp, props), deps);
}
return React.createElement(Comp, props);
};
Memoized.displayName = `memoized(${Comp.name})`;
return Memoized;
}
return React.memo(Comp);
};
export default memo;
Here is how it will be used to compose components
import Todo from "./Todo";
import memo from "../memo";
export default memo(Todo, props => [props.text]);
I have a working codesandbox here — memo-deps
This is what I have observed —
- I should not use
React.useCallback
or any hook inside a conditional statement because React needs to know the order in which hooks are invoked and using it inside a conditional may mess up the order during runtime - But
React.useCallback
works pretty neat in a conditional for my case as I know the order will remain the same during runtime - I am not using the hook inside the conditional statement during render, instead I am composing the component during export conditionally
- I am thinking about React components as plain JavaScript functions and trying to memoize it like how I would memoize a regular JavaScript function
- I could easily replace
React.useCallback
withlodash.memoize
and the end result will be pretty much the same - I don't want to use an external library like
lodash.memoize
or build a custom implementation of memoization whileReact.useCallback
pretty much does the work for me
This is where I am not sure what's happening (these are my questions) —
- React components are not really vanilla JavaScript functions and I cannot memoize them with
lodash.memoize
lodash.memoize
andReact.useCallback
are not the same when I try to memoize a React component- React executes the function before figuring out the render even when
React.memo
is used (maybe to check prevProps vs newProps?) - Is my implementation okay even though it breaks the rules of React? (use hook in a conditional statement)
- How else can I memoize a
React.createElement
if not forReact.useCallback
?
The reason as to why I might want to do this —
I don't want to memoize handlers (closure with a value and event) every time I pass them to a component wrapped in React.memo
. I want to be able to declaratively write memoize dependencies for components.
from Can the useCallback React hook be used conditionally even if it breaks the rules of hooks?
No comments:
Post a Comment