admin管理员组文章数量:1356413
I'm trying to implement helper ponents for CSS Grids. I have something like (prepare yourself):
<ColumnContainer columns={[ "1em", "1fr", "auto", "auto", "1em", "auto"]}>
<ColumnContainer.Row>
{ rowIdx => (
<div style={{ gridRow: rowIdx, gridColumn: "1 / 3" }}>
</div>
)}
</ColumnContainer.Row>
</ColumnContainer>
ColumnContainer
:
- Is a container
div
withdisplay: grid
and various grid properties set up - Is also a context provider
Then, ColumnContainer.Row
:
- Is basically a context consumer
- Takes a function as a child
- Doesn't need to be a direct child of
ColumnContainer
- hence using context
The context provided is an integer, layoutVersion
, which is incremented whenever the set of rows is intended to change (to trigger a re-render), and - hack of hacks - an empty array.
The idea is, as each ColumnContainer.Row
renders, it adds itself (could be any object) to the array whose reference is passed in the context, and renders the child function with the size of the array as the parameter (row index).
Believe it or not, this works, for the first render and if rows are just added to the end.
However, when ponents are added in the "middle" of the ponent DOM, the resulting rendered rows are out-of-order (but not overlapping). Meaning, I think, that in the case of a new layout version (re-render), all the ColumnContainer.Row
s are re-rendered, but not necessarily in the 'natural' order they are in, i.e. in the DOM.
My guess is that depending on ponents to have render()
called in a certain order is a bad idea, as well as modifying the contents of context properties in render()
.
What are my other options - what I really want is to know the 'natural' order of descendent nodes within a ponent tree. If they were direct child elements, I'd guess it would be easy - in my case though I have nested ponents which can output rows.
I'm trying to implement helper ponents for CSS Grids. I have something like (prepare yourself):
<ColumnContainer columns={[ "1em", "1fr", "auto", "auto", "1em", "auto"]}>
<ColumnContainer.Row>
{ rowIdx => (
<div style={{ gridRow: rowIdx, gridColumn: "1 / 3" }}>
</div>
)}
</ColumnContainer.Row>
</ColumnContainer>
ColumnContainer
:
- Is a container
div
withdisplay: grid
and various grid properties set up - Is also a context provider
Then, ColumnContainer.Row
:
- Is basically a context consumer
- Takes a function as a child
- Doesn't need to be a direct child of
ColumnContainer
- hence using context
The context provided is an integer, layoutVersion
, which is incremented whenever the set of rows is intended to change (to trigger a re-render), and - hack of hacks - an empty array.
The idea is, as each ColumnContainer.Row
renders, it adds itself (could be any object) to the array whose reference is passed in the context, and renders the child function with the size of the array as the parameter (row index).
Believe it or not, this works, for the first render and if rows are just added to the end.
However, when ponents are added in the "middle" of the ponent DOM, the resulting rendered rows are out-of-order (but not overlapping). Meaning, I think, that in the case of a new layout version (re-render), all the ColumnContainer.Row
s are re-rendered, but not necessarily in the 'natural' order they are in, i.e. in the DOM.
My guess is that depending on ponents to have render()
called in a certain order is a bad idea, as well as modifying the contents of context properties in render()
.
What are my other options - what I really want is to know the 'natural' order of descendent nodes within a ponent tree. If they were direct child elements, I'd guess it would be easy - in my case though I have nested ponents which can output rows.
Share Improve this question edited Jun 12, 2018 at 7:03 Derek Pollard 7,1756 gold badges43 silver badges60 bronze badges asked Jun 9, 2018 at 17:41 Kieren JohnstoneKieren Johnstone 42k16 gold badges97 silver badges149 bronze badges 11-
Edit: have tried doing a recursive map using something like stackoverflow./a/42498730/376409, but that doesn't look to work with redux-
connect()
-ed ponents, i.e. it won't recurse into them :'( – Kieren Johnstone Commented Jun 10, 2018 at 13:38 - how are rows rendered – Shubham Khatri Commented Jun 12, 2018 at 7:09
-
Could you elaborate on that question please @ShubhamKhatri ? The example above shows how I'd like the
Row
ponent to be used – Kieren Johnstone Commented Jun 12, 2018 at 15:07 -
1
It looks like your problem could related to React reconcilation. Have you tried to use React's
key
? – An Nguyen Commented Jun 13, 2018 at 6:03 - @FiriceNguyen I'm not sure I can see what you mean. There's no mapping/array and so I can't see how a key would e in to it? – Kieren Johnstone Commented Jun 13, 2018 at 6:19
2 Answers
Reset to default 2I have found a dodgy/hacky solution, by having child ponents 'register' themselves (a unique ID and ref) with the container ponent via a callback injected in the context.
The container ponent accumulates these callbacks using functional state updates and setting a flag in the state that a re-calc is required.
The container's ponentDidUpdate
checks the re-calc flag and pares all of the DOM notes (via the refs) using the browser DOM function pareDocumentPosition
. The next state update clears the re-calc flag and includes the order of each of the children's IDs.
This state is then passed down to all children via context, where they can look up their index by ID.
Clearly that sucks but it's all I have for now. Would still like to award bounty to a better solution.
It seems that you rely on render()
to provide you with the recursive structure inside your DOM Tree
. The reason it works "the first time" is that all the ponents need to be rendered the first time they are presented to react
.
However, subsequent render()
calls on ColumnContainer
do not imply renders on the sub-ponents because their state
or props
might have not changed.
I think you should try the following:
- Change your
ColumnContainer.Row
registration to theColumnContainer
array in a way that the children rembemberrowIdx
in theirstate
on the first call and then reuse this value for subsequentrender
calls.
(so to do this effectively you would need:)
Change your registration procedure in two function calls (these two functions should be in your context):
- a function that gets the
rowIdx
for a child and remembers it. (this function is only called if you don't have a cached value forrowIdx
) - a second function that does the work but does not need
rowIdx
as a parameter. (this function is called just like now, every time).
- a function that gets the
本文标签: javascriptReact Get component order within hierarchyStack Overflow
版权声明:本文标题:javascript - React: Get component order within hierarchy - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744066643a2585121.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论