I’m working on a development tool that lets you create React components.
A user will start off with their component looking like:
function MyComponent() {
var rand = useRef(Math.random());
return <div>{rand}</div>;
}
but then might want to modify it like so:
function MyComponent() {
var rand = useRef(Math.random());
return <span>{rand}</span>;
}
The only meaningful change here was <span>
, so ideally for me (to prevent full tree remounts for larger apps/preserve application state), that random number wouldn’t change because the ref would be preserved – but React seems to detect the change in reference to the component definition when considering its identity: MyComponent !== MyComponent (new)
and outputs a different random value.
This is similar to implementing HMR (Hot Module Reloading) myself – but constrained to just react component definitions.
Here is a working example to play with: https://jsfiddle.net/83xruyL5/1/
Is there any way of modifying this React behavior with something like a name/id/key attribute on the definition? Or perhaps a more generic JS approach of preserving/reusing a function/component reference while modifying its definition?
I assume this may not be possible, and am just going to be limited by React here, but am asking just in case it is.
2
Answers
The useState set function will trigger a re-render anyway, and by default, when a component re-renders, React re-renders all of its children recursively. In some cases, if you need to skip the re-rendering of components, useMomo could help.
Also, avoiding some re-computation for this example is possible by passing refs or state props.
Pass ref:
Pass state:
You could use
Calling
setComponent(MyComponent2)
will re-render the wrapper, with the newComponent
but the same ref. The trick is to callComponent
as a function not to create a<Component {...props}>
element. Of course, this will fail horribly if the old and new component use different hooks.Instead of this hack,
I suggest you look into the internals of React to see how they implemented hot module reloading themselves. There is react-refresh to allow "Fast Refresh", provided by the React team.