Implement front-end (React) routing library

Created on 5 July 2024, 6 months ago
Updated 15 August 2024, 4 months ago

Problem/Motivation

Users will need to be able to link to specific components on a node and, later, specific settings views/panels/modals. To facilitate this we should use a routing library. For example we will want to enable links such as /xb/component/3 to open the contextual sidebar for a specific component or /xb/settings/page to open a modal in which a user can set things like the page title and url.

There are 3 popular contending popular router libraries that we can pick from

https://tanstack.com/router/latest
A powerful React router for client-side and full-stack react applications. Fully type-safe APIs, first-class search-params for managing state in the URL and seamless integration with the existing React ecosystem.

https://github.com/molefrog/wouter
Wouter is a tiny router for modern React and Preact apps that relies on Hooks.

https://reactrouter.com/en/main
React Router is a lightweight, fully-featured routing library for the React JavaScript library. React Router runs everywhere that React runs; on the web, on the server (using node.js), and on React Native.

My feelings, briefly, are

Tanstack router is popular and makes a big deal of being typesafe. I see some criticism about it's complexity and it seems heavily tied to SSR with Next.js which is not something that this project requires. It may be slightly overkill for our use case however it will certainly not limit us.

Wouter is small and lean. It seems to offer the functionality this project needs and has a low overhead and small but functional API. It is the least prolific though .

React Router seems to have quite a lot of negative sentiment around the latest v6 release compounded by a history of making breaking changes. It has been combined with/build in tandem with Remix which is not something we are using in this project. It has a large community and is very well documented and powerful.

๐Ÿ“Œ Task
Status

Fixed

Component

Page builder

Created by

๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom jessebaker

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @jessebaker
  • ๐Ÿ‡ซ๐Ÿ‡ฎFinland lauriii Finland

    @jessebaker Which of these options would you recommend?

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom jessebaker

    I'm spending my day today trying to come to a conclusion on that. I have not used any of them before (although I did briefly investigate react-router during our initial estimation phase) so I'm doing some investigation/exploration. I opened the ticket in the hope that others might put forward their opinions before we have to take a decision.

  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands balintbrews Amsterdam, NL

    Great summary and assessment, @jessebaker! Here are my thoughts in addition, hoping they could be helpful to make the final decision.

    I think of the three libraries as three different options on a spectrum that goes from small and lean to robust and โ€œenterpriseโ€ โ€” wouter and TanStack Router being at those two endpoints, respectively.

    Based on my understanding, the primary role of a routing library in XB will be the ability of deep linking. (Besides the code organization benefits that come from using a router instead of manually managing application state/context.)

    Based on that, to me the easiest option to rule out first would be TanStack Router. It can do quite the heavy lifting, with its included devtools, its focus on type safety, all those things that are great when youโ€™re working on a fully-featured app with complex data fetching logic.

    Comparing wouter and React Router, I donโ€™t think XB could go wrong with either, because the routing code in XB will be minimal, and since wouter already mimics some parts of React Router, it would be easy to switch between the two if that becomes necessary for any reason.

    If I had to choose, my vote would go for React Router for the following reasons:

    1. Itโ€™s a critical part of Remix, which is owned by Shopify. Hydrogen, Shopifyโ€™s headless stack is built on Remix. They invest heavily in the ecosystem (e.g. they recently announced Hydrogen Visual Editor โ€” btw, there's probably some useful inspiration for XB there).
    2. Many React devs already know React Router (or a version of it), as it existed long before Remix. (The team who built React Router built Remix.) For a long time, there wasnโ€™t really a question of what router solution you choose if you have a React project, so many React devs have used a version of React Router in the past. Iโ€™ve heard from agencies that have older single-page applications they built for clients with React, that Remix is really great for them, because they can easily migrate, since the router solution they used is the same as what's in Remix. (Now, I realize this may not be as straightforward as it sounds due to the breaking changes between major versions.)

  • ๐Ÿ‡จ๐Ÿ‡ทCosta Rica roaguicr

    Seconding the @balintbrews comment, React Router is heavily used in modern React apps and is well-known by most React developers (who may eventually contribute?). Probably the best approach.

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    To expand on #3: @jessebaker built a PoC during the risk minimization early days of XB that used React Router: https://git.drupalcode.org/project/experience_builder/-/tree/poc_reactro...

    Based on #3 + #4 + #5, it seems pretty clear that React Router is the strongest contender (especially given the swappability mentioned in #4).

    @jessebaker, let's go? ๐Ÿ˜„๐Ÿ˜„

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom jessebaker

    Thanks to everyone for the input so far. I think as @Wim Leers says, it seems we have a pretty strong consensus forming around React Router and my quick look at all 3 last week has confirmed that I don't think Tanstack's offering is the right fit for us. Given the apparent ease of switching between the other options I'm going to write a basic React Router integration and we can go from there.

  • Assigned to jessebaker
  • Status changed to Needs work 6 months ago
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Aight, signaling that new issue status ๐Ÿ˜„

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States ctrladel North Carolina, USA

    I don't have any specific feedback on which library is best, react router has generally done everything I've needed.

    We'll want to make sure there's a good path for integrating Drupal's translations with whatever option is chosen. I've had challenges in the past making sure small SPA type components are able to effectively use Drupal's translations. From what I've found interface translations are heavily dependent on Drupal's html responses either through the initial page response or ajax responses rendering twig or using Drupal.t() in javascript which is dependent on drupalSettings being populated with the initial page response or an ajax response. This poses a challenge when you want to get the translated title for a pop up or component edit pane that is only rendered from JS without requiring an html request to Drupal.

  • ๐Ÿ‡ฆ๐Ÿ‡บAustralia larowlan ๐Ÿ‡ฆ๐Ÿ‡บ๐Ÿ.au GMT+10

    Can you elaborate on why we need a router? At present all of the important parts are covered in the redux slices, eg selected component, open panes etc

    We could easily add a listener middleware that used history.pushState and UrlSearchParams to represent these as url query Params. Then all we need to do is read these back when creating the store

    I've got plenty of client projects I could adapt for a POC of this

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom jessebaker

    @larowlan I'm thinking that I want to enable a user to be able to copy/paste the URL to direct a colleague to a specific part of the experience builder.

    It's very early days yet so at first /xb/component/:componentId will open the Contextual Panel for a specific component.

    Later we may want to go as far as having /xb/page/:pageId/component/:componentId/settings/styles to link to the style settings tab of a specific component on a specific page.

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom jessebaker

    @larowlan I'm going to be mostly AFK for the next day or so and haven't been able to make as much progress on the React Router implementation as I would have liked.

    If you have a PoC you can share without spending a huge amount of time, I'd be interested in seeing your proposed solution.

  • Merge request !843459235: Add POC of urlParams โ†’ (Closed) created by larowlan
  • ๐Ÿ‡ฆ๐Ÿ‡บAustralia larowlan ๐Ÿ‡ฆ๐Ÿ‡บ๐Ÿ.au GMT+10
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Thanks, @larowlan! ๐Ÿ˜„

  • Merge request !90Resolve #3459235 POC "React router" โ†’ (Merged) created by jessebaker
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    What's next here?

  • First commit to issue fork.
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom jessebaker

    Current Status:

    Due to my ongoing challenges in getting Cypress tests working locally, there is still a requirement for tests on this work.

    Tests that still need to be written are:

    • [e2e] A test that visits the XB, selects a components and checks that the URL is /xb/component/
    • [e2e] A test that visits the XB, selects one component and then another and then uses the back button in the browser and is able to navigate back through the two selected components and back to /xb.
    • [e2e] A test that visits the XB and opens the component sidebar (to the correct component) via the
      element in the TopBar.tsx

    The first test ensures that setting the selectedComponent state updates the URL.
    The 2nd ensures that the browser history states are working correctly.
    The 3rd ensures that navigating via the URL updates the state.

  • Issue was unassigned.
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Reflecting #19 in the issue metadata โ€” and the fact that @jessebaker is going on PTO tonight.

    That means this issue is ready to be pushed to completion by writing the required tests documented in #19 ๐Ÿ‘

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States bnjmnm Ann Arbor, MI
    • The contextual form seems to be loading an older version of the form - I'm guessing the MR moved some stuff around which would up preserving some code that has since been refactored
    • Clicking a component to make it active/selected takes us to /xb/component/ which is great, but refreshing a page on that URL results in a 404. While I'm very OK with incremental progress, refreshing the UI page is something I do frequently while developing for it and I'd like it to at least redirect back to /ui
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States bnjmnm Ann Arbor, MI

    Re #21

    • Turns out it was old stuff that was still there but we didn't see due to it being black text/black BG.
    • I pushed a fix for this.
  • Status changed to Needs review 5 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States bnjmnm Ann Arbor, MI
  • First commit to issue fork.
  • Pipeline finished with Skipped
    5 months ago
    #239734
  • Status changed to Fixed 5 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States hooroomoo
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    This caused a regression: ๐Ÿ› Regression: prop labels present on field widgets, but invisible Active .

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024