react-router v6.4+ loaders, actions, forms and more

react-router 

  • react-router is used for in app single page app navigation, we configure routes for pages in the app to map to components
  • react-router has over 1bn downloads, its an industry standard (but there are others e.g. Nextjs router)
  • many apps use react-router, many on v5.x

the new react-router 6.4.x

  • the newest major version of react router v6.4 is a significant enhancement which adds a lot of new features. react-router v6.4 offers new features to load data (loaders) and handle actions (actions). 
    • It's done gone all Remix-y which makes sense because the same guys wrote both.
  • eliminates a lot of boilerplate code to fetch data in useEffect() and set various loading states
  • put your data load and update logic in react-route components instead of custom code
  • unlike Remix, react-router v6.4 is still just all on the client (not server like Remix)

paradigm shifts

Lets start with a couple of high level ideas; "back to the future" so to speak OR "what's old is new again"

  1. back to web basics, react-router v6.4 uses “web standards” mental model of page loading and form submission
    • forms, methods and actions, Request, formData, ids and more
    • this mdn doc is a good place to re-learn
    • forms and actions will probably be a big part of your app
    • uncontrolled controls, don't have to control with react if you don't need to (often do, but don't have to)
  2. "groove is in the heart" and “state is tied to the url” instead of global state redux
    • model app state in the url
    • e.g. configure routes and have then code Forms to submit to those 
      • list:   path="/myapp/users"
      • view:   path="/myapp/users/:userid"
      • edit:   path="/myapp/users/:userid/edit"
      • delete: path="/myapp/users/:userid/delete"
      • for example, see: https://reactrouter.com/en/main/start/tutorial#deleting-records

more details on features

data loading

  • provides data loading hooks to initiate data loading during a navigation (https://reactrouter.com/en/main/start/overview#data-loading)
  • new loader property in a Route, which takes a fn which allows you to load data (return a promise)
  • then the data is available using their useLoaderData() hook
  • so no need to write fetch code in useEffects to load data

data mutation

  • new action property in a Route which takes a function, new Form and new fetcher.Form
  • meant to handle mutations e.g. create/edit/delete
  • typically connect a react-router Form and action to map to an action (just like you would a regular html form)
  • see example: https://reactrouter.com/en/main/start/overview#data-mutations

enable this to start with by using a new "data router" to support these loaders and actions (data apis), use createBrowserRouter and optionally createRoutesFromElements 

  • see https://reactrouter.com/en/main/routers/picking-a-router#using-v64-data-apis
  • new data router is similar to previous versions but a new RouterProvider replaces BrowserRouter and is passed routes created by createBrowserRouter() 
  • you could put routes in the route config under the /routes folder (or /pages folder); though the Error element page is not a route

actions and loaders are also "a thing" in remix, which is now brought over to react-router, but unlike remix, in react-router loaders & actions run on the client, not the server

  • the same guys who created react-router also created remix (Michael Jackson, Ryan Florence)
  • yes, you can continue to use react-router using BrowserRouter and not use loaders, actions and more (but react-router recommends upgrading)

form handling

  • HTML form submissions cause a navigation in the browser, just like clicking a link. react-router Form prevents the browser sending the request to the server (as normal) and instead sends it to the route action instead
  • "By convention, React Router uses this (the Form POST submission) as a hint to automatically revalidate the data on the page after the action finishes. That means all of your useLoaderData hooks update and the UI stays in sync with your data automatically! Pretty cool."
  • set names in the form fields so can get referenced to extract the vales
  • action receives a standard web request object which has a formData() method which can be used to get form values
  • so something like this code:

<Form method="post">

  <button type="submit">New</button>

</Form>

...will route to your action method defined for that route

export async function action() {

  await createContact();

}

...after you add that action as an action on the Route config

    action: action,

Did you know you can have a form submission button outside of a form and link it to the form? you can, using the html id of the form and then matching that to a buttons form value! That's html innit!


references

react-router docs, very good tutorial: https://reactrouter.com/en/main/start/tutorial

tutorial: https://www.youtube.com/watch?v=L2kzUg6IzxM

code: https://github.com/remix-run/react-router/blob/746dc480bf496e5fa8a4fe45e4059bdedee2a5b6/packages/react-router-dom/index.tsx



Comments

Popular posts from this blog

deep dive into Material UI TextField built by mui

angular js protractor e2e cheatsheet