Understanding Component Render Timings with Contexts and <Show />
Seems like I have a gap in my understanding of something with regards to render timing of components when using things like
<Show>
with contexts. I have the following:
The implementation of <Chart />
is the following:
And lastly, my <LineSeries />
component is the following:
The issue is, when I try to run my App component that is supposed to render the Chart and LineSeries, I get the following unexpected error:
This is unexpected to me because within the implementation of <Chart />
I am making use of the <Show />
component to prevent the showing of the children until the chart instance is ready and can be passed to the context. It appears as if there is some eager kind of rendering going on that I did not expect.
Is there a best practice way to go about this intent I am trying to achieve? In my head, even though I pass <LineSeries />
as a child to <Chart />
in my call-site App component, I would expect <LineSeries />
to not render until the parent <Chart />
has done what it needs to do. I'm definitely suspecting a gap in my thinking somewhere here.73 Replies
it's probably because of your use of mergeProps and passing those values into
createChart
I would split props first to pull either the values you want out or at least the children
The reason it's probably causing the issue is because the children are being read in some other part before the showmy guess would be that something somewhere is accessing
props.children
accidentally, maybe something inside createChart(chartContainer, _props)
?I think the likelihood of that is probably low -- that
createChart
API comes from an external, normal/vanilla JS library that I'm just wrapping around with Solid.iirc already doing
Object.keys(props)
could be doing it
you could const config = splitProps(props, ['children'])
and pass that to createChart
to sanity checkLet me try that -- I think that may be what @REEEEE was perhaps alluding to earlier
a ye exactly lol
So I did the following and still no dice ðŸ˜
code looks good to me
is it hmr related or it never works?
It appears that maybe there's something to do with the Context Provider lifecycle....like, even if I had my children wrapped with a provider, maybe it's collaboration with
<Show />
is causing some render timing issue where the context isn't ready?another sanity check: try add the context and the useContext-hook in another file and import from there, maybe it's some weird side-effect of a circular dependency
It never works, but oddly enough, I just tried getting rid of the
<Show />
entirely, and it works. But obviously, I now have to add guards everywhere to all my child components because the context value is potentially undefined.
Not sure if that breadcrumb reveals anything of interest to determine the root causemm very strange
Yeah, I did that as well -- I have a serpate
context/chart.tsx
file where I dumped the creation of the context and the convenience useChart
context hook and I import that across the components.but it also includes the jsx of the
Chart
-component right?Still didn't work with the
<Show />
in place
No, I kept the root <Chart />
component in its own file since the all the child components are just going to consume the context hook
And the <Chart />
just imports the context to set the Provider valuegotcha
ok then i m out of straws to pull 😅
Same here haha!
I'm like, "What is going on here?! WHAT AM I MISSING!?"
would be handy to have a minimal representation of it in the playground to play around with
dev life
I'll see if I can get a playground set up. Does it support bringing in dependencies? Or maybe I can try mimicking the problem
it actually does, you can import any external dependency and it will load it from
esm.sh
but ideally you wouldn't need dependencies to recreate the bug@bigmistqke sorry, I'm not good with using the Playground yet: https://playground.solidjs.com/anonymous/6a8456c7-34fd-43e7-a759-fee5f3967902
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Not sure how to render the content in the playground REPL
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Ah, nice, that's good to know how to do that.
looks like it works fine there so maybe ssr related?
It looks like it's behaving properly?... 🤔
This is all happening client-side actually 😅
oh lol
Simple SolidJS SPA in my case
I definitely think it's something with the children being read from props early or something
me too
Man, I'm just trying to think what is doing that actually. Because that layout I gave at the start is literally all that I'm doing. Basically, it's just a small sandbox of me rendering these basic components
I stripped out the
children
earlier like you suggested using splitProps
Any chance you could do the same setup in the playground with the chart library? You should be able to import the library (it'll show an error but it should import)
Yeah, I'm embarking on creating more data visualization libs for the community so I'm building a Solid Wrapper around Lightweight Charts from Trading View
GitHub
GitHub - tradingview/lightweight-charts: Performant financial chart...
Performant financial charts built with HTML5 canvas - tradingview/lightweight-charts
So how would I import that into the playground exactly? I'm a noob in this department 😅
Just add the import statement to the top, it'll auto import I think
or @bigmistqke does he need to add it to import map?
Just in case it doesn't import automagically, I think adding it to the import map at the top should work

simply adding the import should be enough!
@bigmistqke @REEEEE check this out https://playground.solidjs.com/anonymous/f08c8a6d-5bfd-4fe9-a386-8103caf4fdf2
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
This should recreate it -- it may not be exact, but what I can see is that, the library injects stuff into the tree when you get rid of the
<Show />
component entirely. But when you keep it, the containing <div />
basically stays emptyLooks like the library is modifying the children elements
You could wrap the parent with the show + context or wrap the show with a div
actually I guess you can't wrap the parent with the show + context cause it needs access to the container to create the chart obj
And thus you see my dilemma 😅
I thought along those same lines
I also forgot to give the Chart a width/height so this playground will be better to see the actual chart: https://playground.solidjs.com/anonymous/cc36b2da-ed1f-4eb7-bd2c-d4fae3a18ff6
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
That one is without the
<Show />
component thereI put the show back and it works?
Okay so if you use the callback form it fails
but if you add keyed it works fine
can u share playground, it doesn't on my end
I tried both with and without callback form for Show and I got nothing
Same here
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Holy crapola...
What does
keyed
do ? Never used it beforeSolid Playground
Quickly discover what the solid compiler will generate from your JSX template
actually this is weird, I didn't realize I didn't call chart in the when condition
instead of
Wrapping the show also fixes it
https://playground.solidjs.com/anonymous/57390045-3afe-48f6-b384-89b350988112
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
a yes, it's not actually doing the condition correctly
yes, something about the dom being manipulated does not mesh well with the
Show
inside the jsx-nodeYou guys are incredible -- that fragment trick is chef's kiss man
worth adding an issue to
dom-expressions
Adding a dummy element
https://playground.solidjs.com/anonymous/aeaa3753-6e05-4ce9-9c3c-caadf06c91e0
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
I was about to say, is this an edge case that's worth raising awareness to?
i think so!
it's a big feature for solid how it can work together w vanilla js libraries
Just curious -- how would you characterize the nature of the problem we're seeing here? So clearly the library is doing stuff to the container it is meant to bind to/target. Effectively, that's not playing nice with JSX children and screws up their rendering with context?
Also, first time hearing about
dom-expressions
-- I consider myself a mediocre dev so I'm trying to catch up with everyone's skills 😅dom-expressions
is the library that is powering solidGitHub
GitHub - ryansolid/dom-expressions: A Fine-Grained Runtime for Perf...
A Fine-Grained Runtime for Performant DOM Rendering - ryansolid/dom-expressions
you could add the issue to solid's github too 🙂
bit blurry which library is responsible for what
What's a good way to summarize this? Not sure I have the right words for it haha
yes, something about dom manipulation breaking context in jsx
This is super awesome -- you guys have been a massive help!
Thank you!
Ur very welcome!
directly mutating dom controlled by UI framework is not advisable.
this may or may not be a bug, you can just put the reproduction as an issue and describe the issue, you are not to be expected to know about dom-expression
as another alternative you can
move your provider outside the JSX
https://playground.solidjs.com/anonymous/16c8c567-6341-4120-a160-491da12c4c9b
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
I am not sure if I agree: having a container element and doing stuff w a vanilla library is pretty solid, especially if you are not rendering additional dom elements in it.
which part you do not agree?
directly mutating dom controlled by UI framework is not advisable.this ?
Yes, exactly!
mutating the dom directly may be like pulling the rug under the framework. ( not in all cases)
but in this case, if the
show
adds placeholder element , and the external code remove it, expectations are not meet and things can break.A I see what you mean, but that's not this bug. In this situation the children are not adding dom elements, they simply add config for the library through context, and then return null.
I don't think these nulls are injected in the DOM.
It is the external library that mutates the container the show is in
I am not excluding that there might be something that can be better handled on solid side.
but I think the better practice and the general rule is not to change dom
that is controlled by the framework