-
Notifications
You must be signed in to change notification settings - Fork 47k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add useReactPath hook for reflection and stable IDs #15435
Comments
The specific use case you've outlined here could be solved with a different
This will return the ids |
Hi @nmain - thanks so much for the speedy and thoughtful reply! I actually use a similar pattern elsewhere, with My concern here is that the deterministic execution order is (as far as I know) just an effect of current implementation details in |
you are dreaming |
@mike-marcacci That's a good point. The stability of |
(shameless plug) @mike-marcacci , I don't have any Looking at your prior example, you could write something like:
render
and observe conditions like the following
I'll admit that it's very manual and it would be nice to have a canonical approach supported internally in React (esp. for compatibility between libraries), but I think there can also be benefits to being able to declare your own path hierarchies for different purposes -- perhaps: test automation ids, accessibility/analytics tagging, or external state management. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution. |
This kind of repeatable, stable ID continues to be impossible without a solution that is aware of a components position in the tree. As concurrent moves towards stability, this is increasingly important, as it breaks the hacks that are currently in use. |
this is being handled in #17322 I believe @mike-marcacci |
@jquense very interesting; that does indeed address the same use-case, albeit in a way that requires re-rendering on mismatch. I see these as competing approaches that address the same problem, so if that route is chosen, this can be closed. However, I believe this may be a superior approach. |
If there is an interest in this approach and I can get a nod from someone on the react team that it's a direction that would be considered, I can go ahead and implement it. |
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment! |
@mike-marcacci Can you describe in more detail why you consider this a better approach? |
Hi @gaearon, I haven't read through the most recent (merged) implementation of Basically, my primary motivation is similar: to allow creation of an identifier that is stable across serialization and hydration. My implementation strategy is the result of answering this question: "What is naturally unique to a component instance that is already stable across serialization and hydration?" The answer to this is that the "path" in the virtual dom tree (taking "key" into consideration) is not only unique across serialization/hydration but is also the mechanism used internally by react to identify an "instance" of a component. Either exposing an element's position directly as I've proposed, or using it as the basis for generating an opaque identifier, solves this problem without requiring us to keep track of any additional state. This is a pretty important feature in my eyes. |
OK, just skimmed through #17322 and I see that this state is being persisted via attributes on the serialized HTML. This is probably a pretty reasonable way to persist state here, although prefixing IDs with Either way it sounds like the merged approach solves my actual use-case, so I'll close this issue. Also, by creating a new hook primitive that's designed to be used as a "totally opaque identifier" it would be perfectly possible to switch out the underlying mechanism if there was ever a desire. |
With the strategy you're proposing, I think the length of IDs would keep growing the deeper we get in the tree. Is that a concern? |
(To be honest I don't have the background on the design in #17322 other than that the keypath was probably considered. After all, React did emit keypath in early versions as an attribute, although mostly as an implementation detail. But I'd also be curious to understand in more depth how these approaches compare.) |
@gaearon - ya, identifier length was something I considered too, and so this proposal was focused on exposing a primitive that could be used for generating such an identifier among other things. In my own experiments for this (and similar problems elsewhere) I relied on generating a stable hash, which is surprisingly performant especially given the fact that the value is subsequently memoized. However, it does lead to considerably longer identifiers (128 bits, for example) than a counter, which could be an issue if huge numbers of identifiers were used on the same page. |
Makes sense. I think another concern with using the keypath as a generic identifier is that the keypath will change over time. Either you'll only get the initial one (but then it might clash for a client-only newly mounted component that happened to mount in the same place at some later point). Or we'll have to issue state updates for every component that uses a keypath whenever any of its parents is reordered. That doesn't sound very promising. |
@mike-marcacci this was super interesting! I also had a need for stable unique IDs per component instance, and after a lot of experimentation and iteration, also landed on a very similar "path" approach (SSR wasn't a concern in our specific case), which I ran through imurmurhash and then memo'd. Pretty cool to see it discussed here. |
Do you want to request a feature or report a bug?
Feature: this is a proposal that would solve #1137 and other similar cases by providing a reflection hook that retrieves the path in the react tree to a component.
What is the current behavior?
There is currently no mechanism for finding a component's path in the react component tree without using unstable, internal APIs.
What is the expected behavior?
There are a wide range of use-cases that require stable, unique namespaces that are stable across app instances.
My particular use case is rendering SVGs that include
<defs>
blocks. The challenge is that these definitions are all globally scoped. It's fairly easy to get around this by prefixing these definitions with an id that is stable and unique to the component instance:While this works well, the generated ID is different each time a component is instantiated. This means that it's not possible to safely rehydrate server-rendered SVGs, as the HTML will have the wrong prefix.
Instead, I would like a hook that provides the react path to the current component. For example:
We would expect the path to be:
This array could then be used much like an XPath for testing automation purposes, or hashed into a unique ID or prefix, for purposes like mine.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
This has never been possible.
The text was updated successfully, but these errors were encountered: