Hi Jed. First, thanks for providing a solid starting point. I was running into an issue while building https://observablehq.com/@gnestor/react-components where more than 1 instance of a component that uses the Observable helper APIs (useSetter, getValue, setValue) would return a Javascript object vs. rendered component, so each additional instance would essentially render to the original instance's DOM node vs. their own. I will create a demo of what I mean...
Check out https://observablehq.com/@gnestor/react-components-using-j-f1-react. You'll notice that the only demo components that render are the `renderedDate` and the combined one at the bottom. All of the "rendered-" components are wrapped with `renderWithSetter` which wraps them in a `useSetter` so that these components can be used much like @jashkenas/inputs. However, since they're all using the same `useSetter`, only `renderedDate` renders correctly (because it was the first to render apparently) and the rest just return JS objects.
Thanks for telling me about that! I hadn’t thought of the use case of wrapping these in a helper function when implementing them at first. I went back and added some more logic to allow you to provide additional data for the key, or to override key-based lookup entirely (see the new documentation for `render` in the React notebook) and a one-line change to the fork you sent over brings it back to correct behavior: https://observablehq.com/d/b09885fd880f3092
The reason it’s useful to still use the cache to some degree is:
for render() it keeps the same HTML element, allowing React to update only the parts of the HTML that changed.
for component() it keeps the identity of the returned function the same, which means that it can keep its state and other stored values (like useRef, useMemo, and useEffect) when the values of variables inside it are changed by user interaction with other cells.
Hopefully all this stuff works properly, but please let me know if you run into any issues!
Ok, your changes fixed it 👍 I don't fully understand the need for a cache. Are you saying that without it, every re-render will destroy the original root node and render to a new one?