solidjs / solid

A declarative, efficient, and flexible JavaScript library for building user interfaces.
https://solidjs.com
MIT License
32.35k stars 925 forks source link

Multiple child elements in Context.Provider #85

Closed deniss-muhla closed 5 years ago

deniss-muhla commented 5 years ago

Can we use multiple nested elements in Context.Provider?

When 2 or more elements inside Provider component then nested Context consumer components won't get context data.

return <CounterContext.Provider value={store}> <canvas forwardRef={(r) => setState({canvasRef: r})} ></canvas> {(props.children)} </CounterContext.Provider>

Created sandbox as example. https://codesandbox.io/embed/counter-context-hhxhw

ryansolid commented 5 years ago

Thanks for reporting. I can confirm this is an issue and I see what the issue is. I will need to verify this is the only place that suffers from this issue to decide the right solution. But basically nested dynamics aren't being resolved until DOM insertion time which means they are getting processed outside of the Context. An easy fix but I need make sure there aren't any other implications.

ryansolid commented 5 years ago

Ok I've beefed up my tests in this area and have updated the behaviour for Context children to be much more robust. Your issue should be fixed in Solid v0.11.2.

deniss-muhla commented 5 years ago

Thanks. Will check this later. About DOM elements. Can we create in components tree a brunch which starts with context provider with some DOM element like canvas and with nested components completely without DOM elements inside?

function DeclarativeVirtualComponent(props) { return props.children; }

Something like custom react renderers as react-pixi, e.t.c.

P.S. Very interesting library.

ryansolid commented 5 years ago

Oh that is interesting. I've never thought about doing so, but yeah there are no restrictions on what you return from a component. Somewhere it will try to insert into the DOM, but inserting nothing is perfectly fine. If the components all return nothing except the top-level context provider returning that Canvas that'd be legit. Looking at how React Pixi works it doesn't really leverage Reacts diff engine. It's just tricks to wrap imperative commands. Using Solid's reactivity you could write similar imperative commands. I suspect it would work a little differently. Probably potentially more efficiently since there is no need to execute as much of the tree. However, there might be other performance gotchas depending on the patterns attempting to be used. Really interesting. I didn't think about how this could be a side-effect of my Component design. But seems completely doable.

The difference between React and Solid is that the compiler does more right now. But this Virtual approach depending on the Runtime is perfectly fine. Something like React Native I imagine would be a little different. I was looking at doing something with NativeScript at one point, but at the compiler level since it was set of elements. The thing is JSX is great at covering imperative API's with a declarative one. But the compilation step is actually to turn a declarative API into an imperative one. But for an API that is already imperative the compilation step actually needs to do very little. Well something for me to think about.

deniss-muhla commented 5 years ago

Thanks for deep and complete answer. Had same thoughts about efficiency when I saw Solid approach to render. Will try later to compare performance of different realizations with solid, vanilla js and react.