attaching dynamic component to render pipeline via shared state
Hi there 🙏 — I’m working on a setup where I want to dynamically “plug in” components at runtime, controlled by shared state, without tight coupling between the components themselves.
I have a central state (e.g. { current: "StepA" | "StepB", data: {…} })
Multiple components (StepA, StepB) are mostly independent – they don’t import or reference each other
The parent component should mount the appropriate Step* into the render tree automatically whenever the state updates
I tried this minimal working example using Solid’s <Dynamic> component
https://playground.solidjs.com/anonymous/a28ef95d-a10e-4976-9ba0-5d910a10454e
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
9 Replies
fixed version: https://playground.solidjs.com/anonymous/f28d7289-9f50-4196-8399-2eed79ca9bd2
changes are:
Adjust
<View/>
-component
in solid components run only once! it's also wisest to use solid's control flow components instead of ternaries.
Your code
my code
replaced functions with components
I would advice to use components instead of calling functions directly for templating.
<Dynamic/>
also expects an (props) => JSX.Element
(aka a Component
) and not a JSX.Element
.
There is no benefit in using solid's createComponent
.
your code
my code
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Register the proper components
your code
my code
Fix types in app.tsx
your code
my code
As mentioned before:
<Dynamic/>
expects a (props) => JSX.Element
Create a new reference for the signal
when signals are updated they are referentially checked, if you want to trigger effects to re-run you will have to spread it. another option would be to use a store, or set the equals-option to false (then it will update regardless of if the value changed or not) setSignal(..., {equals: false})
your code
my code
I didn't touch it but
is a code-smell and could cause bugs because components is not a reactive datastructure:
will not cause reactive updates.
it currently works, but it is very error-prone
i would advice to use a single store to keep all your data in, and to use an object and not a map (stores only do fine-grained updates on arrays/objects, not Map/Set/...)
a better way to write this would be
because doing
will cause an infinite loop and
will not.
I did not touch it because it did not come up in the demo, but:
will not be reactive (see my first comment) . Components only run once
is the most important concept to follow in solid.
also the same comment
const app = getApp();
is not reactive because Components only run once!
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
notice how
-
app.activeComponent
is a derivation: get activeComponent() { return this.components[this.activeComponentName]; }
, this way you only have to set the component-name.
- I shallow-merge the store in addComponent
: setApp("components", { [name]: component })
this will add [name]: component
to app.components
(see docs)Thanks so much for your effort 🙏 I really appreciate it — I’ll try to implement your solution 🙂
you are very welcome!
The application’s Context object is also a standalone App object that holds all the static data (Maps, config, etc.). For state that needs to be reactive (e.g. user: string or other dynamic values), what do you recommend?
Should I initialize a central createStore in the Context provider and expose it to all components?
Or should each component create its own local signals (or even a local store) based on data pulled from Context?
Or perhaps maintain individual signals directly in a global context file?
In other words: static data lives in the shared Context App object, but where should the reactivity layer ideally be built—from your experience?
Should I initialize a central createStore in the Context provider and expose it to all components?yes, that's a good approach. something like:
Or should each component create its own local signals (or even a local store) based on data pulled from Context?syncing state is a code-smell
Or perhaps maintain individual signals directly in a global context file?using individual signals or a store is the same. i would advice for you to use a store. they are very handy, especially in the beginning.
thanks i will build it in today, i have played around with your example, and i think i can build the app the same way 🙂