Sådan opgraderes til React Router 4

Ikke længe efter at jeg begyndte at arbejde på min nuværende stilling, indså teamet, at det ville være nødvendigt for os at opgradere til React 16, så vi kunne bruge et nyt UI-bibliotek, som vi var interesserede i at vedtage.
For at finde ud af, hvor meget tid denne opgradering ville kræve, så vi på alle vores nuværende pakker for at se, om de var kompatible med React 16, og for at se, om vi stadig brugte ikke-understøttede eller forældede pakker.
Begyndelsen af vores kodebase var bygget af udviklere, der brugte det open source- eller tredjepartsbibliotek, de ønskede, uden faktisk at undersøge dem. Således fandt vi ud af, at mange af pakkerne var udfaset og skulle udskiftes ASAP.
En af de største overraskelser for os var afskrivningen af react-router-redux
. Vi brugte react-router-redux
sammen med react-router v3. Dette fik os til at tænke kritisk over, hvorfor vi redux
i første omgang brugte i vores router.
Når vi begyndte at undersøge reagerer router v4, indså vi, at de nye funktioner stort set ville eliminere enhver grund for os til at bruge et ekstra bibliotek til at forbinde vores router og redux
. Så det efterlod os i stand til bare at opgradere fra reagere router 3 til 4 og fjerne react-router-redux
fra vores applikation.
Så jeg fik til opgave at opgradere vores router til v4 efter kun at have været i positionen og arbejdet med React i cirka 2 måneder. Dette var fordi opgradering fra React Router 3 til React Router 4 lød som om det skulle være en triviel opgave. Men som jeg hurtigt fandt ud af, var det lidt mere involveret, end jeg forventede.
Når jeg gennemgik dokumentationen, GitHub-repoen og mange, mange Stack Overflow-svar, samlede jeg endelig trinene til opgraderingen og ønskede at dele mine fund - især for at forklare, hvordan og hvorfor visse ændringer foretages.
Den største ændring at bemærke fra skaberne af React Router er, at opgraderingen fra React Router 3 til React Router 4 er mere end bare at opdatere et par biblioteker og funktioner - det giver dig mulighed for fundamentalt at ændre, hvordan din Router fungerer. Skaberne af React Router ønskede at gå tilbage til en simpel Router, der tillader udvikleren at tilpasse den, uanset hvordan de vil.
Jeg har opdelt denne vejledning i 5 forskellige dele:
- Pakke
- Historie
- Rute
- Rekvisitter
- Redux-integration
Pakke
React Router v4 pakkestruktur ændret således, at det ikke længere er nødvendigt at installere react-router - du er nødt til at installere react-router-dom
(og afinstallere react-router
), men du mister ikke noget, da det reeksporterer al react-router
eksport. Dette betyder, at du også skal opdatere eventuelle react-router
importopgørelser til react-router-dom
.
Historie
Historie er en vigtig del af rutingen, så vi kan huske, hvor vi kom fra, og hvor vi er i øjeblikket. Historie findes i mange former for reagerer-router og kan tage et stykke tid at forklare. Så for at holde denne artikel om emnet, vil jeg ganske enkelt anbefale, at du læser igennem denne artikel, der forklarer historik i forhold til reagerer router 4. Denne artikel skal dække de fleste tilfælde af din brug af historie.
Rute
React Router v3 tillod os at placere alle vores applikationsruter i en fil, som vi kalder router.js. Imidlertid giver React Router v4 dig mulighed for at placere Routes i de komponenter, de gengiver. Ideen her er at dynamisk rute applikationen - med andre ord finder routingen sted, når appen gengives.
Men hvis du har en anstændig størrelse ældre kodebase, du arbejder med, vil du sandsynligvis ikke foretage en ændring så stor. Heldigvis giver React Router v4 dig stadig mulighed for at placere alle ruterne i en central fil, sådan opretter jeg alle vores eksempler. Der er dog et par ældre komponenter og funktioner, der skal udskiftes.
IndexRoute
Tidligere IndexRoute
blev brugt som en rute til nogle standardgrænseflader for en overordnet rute. Men i v4 IndexRoute
bruges den ikke længere, da denne funktionalitet nu er tilgængelig i Route.
For at levere standard-brugergrænsefladen vil flere ruter, der har den samme sti, lade alle de tilknyttede komponenter gengive:
import { BrowserRouter as Router, Route } from 'react-router-dom'; // example of our route components
Så alle komponenterne - Home
, About
og Contact
- vil gøre. På grund af dette kan du heller ikke længere rede ruter.
Derudover IndexRoute
kan du bruge det nøjagtige nøgleord for at give mulighed for bedre matchning uden brug af .
import { BrowserRouter as Router, Route } from 'react-router-dom'; // example of our route components
Eksklusiv routing
Efter tilføjelse af det nøjagtige nøgleord “something.com/about”
vil blive dirigeret til når routeren ser en sti “/about”
. Men hvad nu hvis du har en anden vej “/about/team”
? Som jeg nævnte før, vil routeren gengive alt, der matcher. Så komponenterne er forbundet med både “/about”
og “/about/team”
vil gøre. Hvis det var hvad du havde til hensigt, så er det godt! Men hvis dette ikke er, hvad du vil, skal du muligvis sætte en switch omkring denne gruppe af ruter. Dette gør det muligt at gengive den første sti, der matcher URL'en.
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
Bemærk, at nøgleordet nøjagtigt stadig skal vises for Home-komponenten - ellers svarer det til de efterfølgende ruter. Bemærk også, at vi skal liste “/about/team”
før, “/about”
så ruten går til Team
komponenten i stedet for About
komponenten, når den ser “something.com/about/team”
. Hvis det så “/about”
først, ville det stoppe der og gengive About
komponenten, fordi Switch kun gengiver den første komponent, der matcher.
Standardrute
En standardrute eller en "fang alle" -rute, der almindeligvis bruges til 404 sider, er den rute, du bruger, når ingen af ruterne matcher.
I React Router v3 var en standard Route
:
I React Router v4 blev standard Route
ændret til:
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; // this is our default route
When you don’t include a path in a Route
, the component will always render. So, as we discussed above, we can use Switch
to get only one component to render, and then place the “catch all” route very last (so it doesn’t use that one before the Router
gets a chance to check the rest of the paths), so something will always render even if the other paths don’t match.
onEnter
Previously, you could use onEnter
to make sure the component of the Route
has all of the information it needs or as a check (such as to make sure the user is authenticated) before the component rendered.
This feature has been deprecated because the new structure of Routes is that they should act like components, so you should take advantage of component lifecycle methods instead.
In React Router v3:
Becomes:
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
... componentDidMount() { this.props.fetchInfo(); } ...
Props
In React Router v4, the props passed through the router have changed, as did the way they are accessed. The Route now passes three props:
history
location
match
history
history
contains a lot of other properties and methods, so I won’t list all of them, but here is a selection that might be most commonly used:
length
: number of entries in the history stacklocation
: contains the same information as belowpush(path, [state])
: pushes new entry on history stackgoBack()
: allows you to move the pointer on the history stack back 1 entry
It’s important to note that history
is mutable, and while it contains a location
property, this instance of location
shouldn’t be used since it could have been changed. Instead, you want to use the actual location
prop discussed below.
location
The location has properties:
pathname
search
hash
state
location.search
is used to replace location.query
and it must be parsed. I used URLSearchParams
to parse it. So a URL such as “//something.com/about?string=’hello’”
would be parsed as such:
... const query = new URLSearchParams(this.props.location.search) const string = query.get('string') // string = 'hello' ...
Additionally, the state
property can be used to pass the location
-specific state
of components through props. So, if you wanted to pass some information from one component to another, you could use it like this:
... // To link to another component, we could do this: // However, if we wanted to add state to the location, we could do this: const location = { pathname: '/path/', state: { fromDashboard: true }, } ...
So, once we get to the component rendered by that path, we’ll have access to fromDashboard
from location.state.fromDashboard
.
match
match
has the following properties:
params
: gets the dynamic segments of the path from the URL — for example if the path is“/about/:id”
, in the component, accessingthis.props.match.params
will give you the id in the URLisExact
: true if the entire URL was matchedpath
: the path in the routes that was matchedurl
: the matched portion of the URL
Redux Integration
As I addressed earlier, we found that in our case, we didn’t need to have an additional library to connect redux
with our router, especially since our main use case for this — Blocked Updates — was covered by react router.
Blocked Updates
In some cases, the app doesn’t update when the location changes. This is called a “Blocked Update”. This can happen if both of these conditions are met:
- The component is connected to Redux via
connect()(Component)
. - The component isn’t rendered by a
In these cases, I wrapped the component’s connect with withRouter
.
This allowed the router information to follow the component when it gets linked to, so the app still updates when the Redux state changes.
And that’s it!
Denne opgradering tog mig over en uge - et par dage med at forsøge at finde ud af, hvordan jeg overhovedet gør det, og derefter endnu et par dage til at begynde med at foretage ændringer. Opgradering til React Router 4 er en enorm ændring, der ikke skal tages let, men det gør din router meget mere let og nem at bruge.
Tøv ikke med at kommentere / stille spørgsmål!