-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Navigator
component and the client-side router in side editor
#37355
Comments
No, I wasn't aware of it, and thank you for letting me know!
It is indeed not ideal that we have many routing solutions within the same repo. Out of curiosity, did you consider When working on the Global Styles sidebar and discussing what features the As @youknowriad just explained above, it was decided that there wasn't a need or any of those "advanced" routing features, and that The fact that a client-side router in the site editor was implemented just a few weeks later raises some questions:
|
No I didn't even know it exists when first implementing the custom CSR 😅 .
I was not there in the discussion, so I'm obviously biased here, but IMHO it's a missed opportunity that we didn't choose to implement a more robust solution. Especially given that it's not impossible nor very difficult to support both situations. Many challenges we're facing in this Making it browser-first is preferred if we ever want to implement a client side router in WordPress in the future, which seems like a trend in most modern front-end web apps. It can also unify the client routing solutions in the WP plugins ecosystem (maybe even in Calypso?).
I believe we can make
Yes. This is my original thought when first implementing it using |
Some missing point of discussions here:
I think these are solution indications that the current approach is sound. A lightway navigator that we can plug into the browser history if needed. |
If we want the implementation to be cross-platform, shouldn't we take browser's history stack into account from the start as well? |
@youknowriad , considering the introduction of the |
Yes, I think over time I grow convinced that "Navigator" and routing are independent and we should close this one. |
Based on my recent experience working on the routing logic in the site editor, I have found it to be rather confusing and unnecessarily complicated. If
Currently, both are the sources of truth, and we use both API from We should just choose one as the single source of truth, and this is the reason why I advocate using This is a practice that has been discussed many times before. Implementing this approach ensures a clear and direct data flow, while abstracting away the intricacies of syncing behind a standardized abstraction. Adopting this architecture still allows for the implementation of advanced logic, such as focus management and Many have also voiced their frustration working with the Site Editor's router. I hope that a more architectural change could help mitigate that. Especially since |
That is true, and I have in fact recently opened #51760, since that two way syncing is breaking the focus restoration in I've been personally advocating for having a fully-fledged router in
Judging from Riad's comment above and from the reply in #51760, Riad's proposed solution is that Is your suggestion basically to remove all of the history logic from
Given previous feedback received on other components, is looks like the "experimental" prefix has little value when it comes to defining whether a component is experimental or not. What matters seems to be whether the code has been merged in a core release or not — and in the case of |
I think the Navigator can still keep the history but base it on the "path" prop instead (history of path changes). That said, I still need to experiment with that. |
@kevin940726 My proposal is to use @wordpress/data stores (edit-site store) as the source of truth because that's already the source of truth for all Gutenberg code base. This still requires two-way syncing between "store" and "url" but that's simple. The problem right now is that we also need to sync with the "path" of the navigator component but that won't be needed when we make the navigator component controlled. |
I don't know how two-way syncing would be "simple" to implement though 😅. Even if it is simple to implement, is it simple to maintain, debug, and document? I've never seen any client side router library use the local state as the source of truth, but maybe you have some specific ideas in mind? As pointed out by Dan and the Redux doc, it's not recommended to use local state as the source of truth for URL routing. The only solution I found in the community is
If the goal is to keep it "dumber", then I don't see why making them a bunch of pre-styled divs a bad idea. We can instruct people to integrate them with whatever routing library they prefer, so it's not strictly coupled with Or, we can accept a I'd like to challenge the idea of using the local state as the source of truth. The complication of the router has already been a pain point of working with the Site Editor. I believe keeping a uni-direction data flow can help in the long term. Maybe it's not the problem here? Or maybe I'm missing the bigger picture? Further feedback will be greatly appreciated! 🙏 |
Example: We do already offer APIs like So, we have two options:
Personally, I still think that's the best approach. A single source of truth of all WP state (stores) and URL is just a side effect. |
What's stopping us from taking the |
@kevin940726 That's basically the same thing as what I'm suggesting, the only difference is that the syncing happens in the middleware. It's still two way syncing. |
Maybe we have a misunderstanding of the terms used here. By "two-way syncing", I mean that we have multiple sources of truth that can be updated directly. In this case, there are local state ( For navigating to a new path, the current two-way syncing model looks like: graph LR
A(Components)-->|"navigator.goTo()"|B(Store)
B-->|selector|A
A-->|"history.push()"|C(URL)
B-->|"Sync"|C
C-->|Sync|B
If we're not careful, we might introduce an infinite loop while updating one of the state. The two-way data flow is also hard to debug and maintain. What I mean by a unidirectional data flow is to treat the URL state as the single source of truth and only update that directly. graph LR
A(Components)-->|"history.push()"|B(URL)
B-->|Sync|C(Store)
C-->|selector|A
This data flow is IMO much easier to understand and debug. This is also what React and Redux are famous for compared to their competitors at the time (anyone remembers This is not to say that two-day data flow is absolutely the worst, but it needs to be dealt with very carefully. I don't think we have the resources to maintain such a complex system. I also don't see the benefits of the two-way syncing router from either developer's or user's perspective. Maybe I misunderstood you though! Maybe the proposal you mentioned above is exactly what I described here too? In that case, I'd say we're on the same page! ✋ |
In both cases, people can still do And IMO, Syncing "Store <> URL" is easy to write in a single hook without any risk of breakage if there was no need to update some local state like we do now (navigator internal state). So let's start by doing that first because it's a requirement anyway for any approach (make the navigator controlled) |
I think that it's important that Assuming that
We'd need to be careful in understanding how much of the internal |
That's not what I'm proposing though. In |
Personally I don't like when I see "principles" and "guidelines" mentioned everywhere. I don't think we should be following "principles" blindly, people share principles and ideas on twitter and on the internet because it suits their applications and needs, but adapting them to our own architecture and constraints is something else. Most applications don't need the extensibility APIs of WordPress and its data module. Most applications don't care about providing APIs to register middlewares... Most applications don't care about backward compatibility as much as we do. That said, I'm fine with exploring both approaches and seeing which one is simpler. The reality is that we need to make the navigator component controlled regardless of the approach. |
I'm not saying we should follow the "principle", maybe I misused the word though. It's certainly not blindly either, I think it's important to know why it's an established best practice so that we can learn from them. The proposed unidirectional data flow also came from personal experience and issues others and I have encountered in the Site Editor. FWIW, since we care so much about backward compatibility, I think it's also important to make sure we ship the simplest (can't think of a better word for now) API we can think of so we don't have to risk changing it and deprecating it later. I'm just voicing my opinions and concerns on this subject. I also provided my proposed solutions. We might end up settling on different solutions or making different trade-offs, and that's perfectly okay to me! However, I think it's important and healthy to share my opinions and communicate as much as possible! 🙂 I don't think I have anything else to add here, so I'll back up a little. Thanks for jumping into the discussion with me! 🙇 |
In #37223 (comment), @kevin940726 wrote:
And in #37223 (comment) @youknowriad answered:
The text was updated successfully, but these errors were encountered: