Creating an "group index provider" context
For context
I am developing a group component which places its children in a flex manner.
I want any child of the group (as well as nested ones) be able to access its previous and next sibling sizes in the group, but that seems impossible to do without wrapping each direct child of the group with a context provider.
Also the whole system must be reactive. That is, the children list may get changed or reordered, and the contexts must change accordingly and propagate the updates into the nested children as well.
Explanation
Each child can be any JSX or HTML element, but nested in that child may be a context consumer, which wants to access the index of the direct child of the group widget. So basically there is a context access which may be nested deeply in any of the group's children.
What I tried
The solution I tried was to wrap each child with its own context provider, and pass the index of that child to the provider. But it didn't work because mapping over children requires using the
children
helper (or whatever else) for resolving the JSX elements, which effectively calls the component functions. If the context is asserted to be non-null in any of the nested children, the system simply breaks down, throwing an error.
I tried using runWithOwner
, but it didn't help. After a bit of research, I have found that some people use a counter and a singular context provider to increment the index of each child, but I imagine the the order that the children are resolved in is not guaranteed to stay the same.10 Replies
Example
Simple example for demonstrating the usage of the child index:
A completely bugfree way of doing this with context is impossible afaik. You will not be able to express something like this, for example:
In general conditional rendering and swapping orders will make it that this approach will have bugs in it.
If you don't care about ssr you could do some trickery with MutationObserver observing html element in Group, adding a data-attribute to an element in ShowIndex and querying them whenever the MutationObserver is being called (you will need to handle the edge case of nested Groups).
Another way I forgot to mention is using
jsx-tokenizer
, but it just looks really unpleasant having to wrap each group child with a GroupItem
token.i am the co-author of
jsx-tokenizer
🙂
with the jsx-tokenizer
approach, something like :
would not work either.
it requires it to be direct children
but if you follow that rule jsx-tokenizer
(and the generalized version: returning a non-dom element as JSX and then resolving it in the parent) will give you consistent order of children.No, I meant to require wrapping each direct child in a token component, and then map the token components to context providers in the
Group
componenti see, yes, that could work too
Would this work?
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
yes, i think so.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template