Calling root render multiple times

In React, if you call render on the same root more than once (e.g. root.render(<App someProp={43}/>), React will update the DOM as necessary to reflect the latest JSX you passed. Calling render on the same root again is similar to calling the set function on the root component. What's the suggested way to achieve a similar behavior using solid render(() => <App />, document.getElementById("app"));?
6 Replies
Alex Lohr
Alex Lohr5mo ago
Solid works very different to react; we do not have a virtual DOM, which is an abstraction that allows for reconciliation. While you could call render multiple times, it would just remove everything inside the container and re-render stuff all again instead of reconciling the changes. In Solid, you are supposed to use signals to change your state and let those state changes update the DOM directly instead of relying on an indirect mechanism that first compares the old state to the new one and creates a map of virtual DOM changes that are then applied on the actual DOM. React re-renders by default, Solid only renders once and applies the changes through its reactive core. You can render the same app to multiple containers, though.
sokratis
sokratis5mo ago
Hey Alex. Thanks for the detailed response.I am familiar with the rendering logic of Solid, and I love it. Let me explain my use case and why I need such a pattern. My team and I are working on building UI components, which are served via a VanillaJS SDK. We are in the process of evaluating which internal UI framework we will use. Solid is winning for now. The reason I need such behavior is the following. Imagine an SDK that does window.MySDK.mountFoo(el, props). This method renders a Foo UI (built with Solid) inside el. Currently, I am exploring how multiple invocations of window.MySDK.mountFoo(el, props) with the same el and different props should behave. As you said, by default, SolidJS will just append a new Foo UI in el. However, I feel DX's better if it updates the existing FooUI with different props. There is a workaround by making the mount method smarter, comparing props, and triggering an event that is converted to a signal. I was just wondering if there is an easier way.
sokratis
sokratis5mo ago
You can have a look at the POC if you want https://github.com/SokratisVidros/solid_components_poc
GitHub
GitHub - SokratisVidros/solid_components_poc
Contribute to SokratisVidros/solid_components_poc development by creating an account on GitHub.
Alex Lohr
Alex Lohr5mo ago
You could abstract the rendering in a way that creates a store of your external immutable props and uses reconcile to make a batched update. basically:
const updateMounted = new Map<HTMLElement, SetStoreFunction<any>>();
const mountFoo = (el, props) => {
const setter = updateMounted.get(el);
if (setter) { setter(reconcile(props)); }
else {
const [store, setter] = createStore(props);
updateMounted.set(el, setter);
render(<Foo {...props} />, el);
}
};
const updateMounted = new Map<HTMLElement, SetStoreFunction<any>>();
const mountFoo = (el, props) => {
const setter = updateMounted.get(el);
if (setter) { setter(reconcile(props)); }
else {
const [store, setter] = createStore(props);
updateMounted.set(el, setter);
render(<Foo {...props} />, el);
}
};
This doesn't yet handle unmount, but I guess you get the gist. Does that help you?
sokratis
sokratis5mo ago
Spot on! The store is effectively the external channel we need to trigger reactivity. Thanks a lot Alex! That's super helpful.
baxuz
baxuz2mo ago
Considering that it's outside of render would this kind of store need to be in its own createRoot?
Want results from more Discord servers?
Add your server