html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}button,input,optgroup,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}html{font:87.5%/1.2 -apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;box-sizing:border-box;overflow-y:scroll;}*{box-sizing:inherit;}*:before{box-sizing:inherit;}*:after{box-sizing:inherit;}body{color:var(--app-foreground);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:normal;word-wrap:break-word;font-kerning:normal;-moz-font-feature-settings:"kern", "liga", "clig", "calt";-ms-font-feature-settings:"kern", "liga", "clig", "calt";-webkit-font-feature-settings:"kern", "liga", "clig", "calt";font-feature-settings:"kern", "liga", "clig", "calt";}img{max-width:100%;margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}h1{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:2rem;line-height:1.1;}h2{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:1.51572rem;line-height:1.1;}h3{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:1.31951rem;line-height:1.1;}h4{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:1rem;line-height:1.1;}h5{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:0.87055rem;line-height:1.1;}h6{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:0.81225rem;line-height:1.1;}hgroup{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}ul{margin-left:1.2rem;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;list-style-position:outside;list-style-image:none;}ol{margin-left:1.2rem;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;list-style-position:outside;list-style-image:none;}dl{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}dd{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}p{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}figure{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}pre{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;font-size:0.85rem;line-height:1.2rem;}table{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;font-size:1rem;line-height:1.8rem;border-collapse:collapse;width:100%;}fieldset{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}blockquote{margin-left:1.2rem;margin-right:1.2rem;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}form{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}noscript{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}iframe{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}hr{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:calc(1.2rem - 1px);background:hsla(0,0%,0%,0.2);border:none;height:1px;}address{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}b{font-weight:bold;}strong{font-weight:bold;}dt{font-weight:bold;}th{font-weight:bold;}li{margin-bottom:calc(1.2rem / 2);}ol li{padding-left:0;}ul li{padding-left:0;}li > ol{margin-left:1.2rem;margin-bottom:calc(1.2rem / 2);margin-top:calc(1.2rem / 2);}li > ul{margin-left:1.2rem;margin-bottom:calc(1.2rem / 2);margin-top:calc(1.2rem / 2);}blockquote *:last-child{margin-bottom:0;}li *:last-child{margin-bottom:0;}p *:last-child{margin-bottom:0;}li > p{margin-bottom:calc(1.2rem / 2);}code{font-size:1em;line-height:1.4em;font-family:'Fira Code', monospace;}kbd{font-size:0.85rem;line-height:1.2rem;}samp{font-size:0.85rem;line-height:1.2rem;}abbr{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;}acronym{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;}abbr[title]{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;text-decoration:none;}thead{text-align:left;}td,th{text-align:left;border-bottom:1px solid hsla(0,0%,0%,0.12);font-feature-settings:"tnum";-moz-font-feature-settings:"tnum";-ms-font-feature-settings:"tnum";-webkit-font-feature-settings:"tnum";padding-left:0.8rem;padding-right:0.8rem;padding-top:0.6rem;padding-bottom:calc(0.6rem - 1px);}th:first-child,td:first-child{padding-left:0;}th:last-child,td:last-child{padding-right:0;}a{color:inherit;}a:focus{outline:2px solid var(--app-cyan);outline-offset:0;}a:visited{color:var(--app-cyan);}code.inline{line-height:1em;background:none;}.bOFKFr{fill:currentColor;height:2em;margin:0.25em;-webkit-transform:none;-ms-transform:none;transform:none;}/*!sc*/
.etECvA{fill:currentColor;height:1em;margin:0.25em;-webkit-transform:none;-ms-transform:none;transform:none;}/*!sc*/
.crLEvQ{fill:currentColor;height:1em;margin:0.25em;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);}/*!sc*/
.kpJAMR{fill:currentColor;height:1em;margin:0.25em;-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);}/*!sc*/
data-styled.g3[id="icon__Icon-sc-1w03ldy-0"]{content:"bOFKFr,etECvA,crLEvQ,kpJAMR,"}/*!sc*/
.empDfs{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:1em;border:1px solid var(--app-foreground);border-radius:var(--app-border-radius);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}/*!sc*/
data-styled.g4[id="example__Render-sc-1u0tgm1-0"]{content:"empDfs,"}/*!sc*/
.iXseCQ{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;margin-top:0.25em;}/*!sc*/
data-styled.g5[id="example__FlexRight-sc-1u0tgm1-1"]{content:"iXseCQ,"}/*!sc*/
.eBWeFI{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/
data-styled.g6[id="example__CodeSandboxLink-sc-1u0tgm1-2"]{content:"eBWeFI,"}/*!sc*/
.iyGSwu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin:0;padding:0;color:var(--app-foreground);background:none;border:none;cursor:pointer;}/*!sc*/
.iyGSwu:focus,.iyGSwu:active{color:var(--app-cyan);outline:2px solid var(--app-cyan);}/*!sc*/
data-styled.g7[id="example__ResetButton-sc-1u0tgm1-3"]{content:"iyGSwu,"}/*!sc*/
.pTvQc{max-width:100%;overflow:auto;--grvsc-border-radius:var(--app-border-radius);--grvsc-padding-h:1em;--grvsc-padding-v:1em;}/*!sc*/
.dense .default-mdx-provider__pre-sc-15gdqwx-0{margin:0;}/*!sc*/
data-styled.g8[id="default-mdx-provider__pre-sc-15gdqwx-0"]{content:"pTvQc,"}/*!sc*/
.iojkbB{border-left:2px solid var(--app-pink);padding-left:0.5em;}/*!sc*/
data-styled.g9[id="default-mdx-provider__blockquote-sc-15gdqwx-1"]{content:"iojkbB,"}/*!sc*/
.hoMCCU.slug{font-size:0.75em;margin-left:0.5em;display:none;-webkit-text-decoration:none;text-decoration:none;}/*!sc*/
*:hover > .default-mdx-provider__a-sc-15gdqwx-2.slug{display:unset;}/*!sc*/
data-styled.g10[id="default-mdx-provider__a-sc-15gdqwx-2"]{content:"hoMCCU,"}/*!sc*/
.koMXVa{margin:3em 0 1em;text-align:center;}/*!sc*/
data-styled.g12[id="footer__Container-sc-1pf7cvd-0"]{content:"koMXVa,"}/*!sc*/
.dvvVYp{color:var(--app-comment);}/*!sc*/
data-styled.g13[id="footer__Text-sc-1pf7cvd-1"]{content:"dvvVYp,"}/*!sc*/
.kCIvmz{color:var(--app-comment);}/*!sc*/
.kCIvmz:visited{color:var(--app-comment);}/*!sc*/
data-styled.g14[id="footer__Link-sc-1pf7cvd-2"]{content:"kCIvmz,"}/*!sc*/
.eeUdUW{display:grid;grid-template-areas:'title expand' 'links links';grid-template-columns:1fr auto;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/
@media (min-width:1200px){.eeUdUW{grid-template-areas:'title' 'links';grid-template-columns:unset;}}/*!sc*/
data-styled.g15[id="navigation__Container-sc-18boyty-0"]{content:"eeUdUW,"}/*!sc*/
.khCaEg{grid-area:title;margin:0;}/*!sc*/
@media (min-width:1200px){.khCaEg{margin-bottom:0.5em;}}/*!sc*/
data-styled.g16[id="navigation__Title-sc-18boyty-1"]{content:"khCaEg,"}/*!sc*/
.jyqapB{-webkit-text-decoration:none;text-decoration:none;color:var(--app-foreground);}/*!sc*/
.jyqapB:visited{color:var(--app-foreground);}/*!sc*/
data-styled.g17[id="navigation__TitleLink-sc-18boyty-2"]{content:"jyqapB,"}/*!sc*/
.iKXeho{grid-area:expand;color:var(--app-foreground);width:50px;height:50px;background:none;border:none;margin:0;padding:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/
.iKXeho:focus,.iKXeho:active{color:var(--app-pink);outline:2px solid var(--app-pink);}/*!sc*/
@media (min-width:1200px){.iKXeho{display:none;}}/*!sc*/
data-styled.g18[id="navigation__Expand-sc-18boyty-3"]{content:"iKXeho,"}/*!sc*/
.ktoYoz{grid-area:links;display:none;}/*!sc*/
@media (min-width:1200px){.ktoYoz{display:unset;}}/*!sc*/
data-styled.g19[id="navigation__Links-sc-18boyty-4"]{content:"ktoYoz,"}/*!sc*/
.bwEVJA{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;font-size:1.2em;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/
data-styled.g20[id="prev-next__StyledLinkToSlug-sel85m-0"]{content:"bwEVJA,"}/*!sc*/
.fhnjmd{display:grid;grid-template-areas:'left-void nav right-void' 'left-void content right-void';grid-template-columns:1fr minmax(0,85ch) 1fr;padding:0 0.5rem;}/*!sc*/
@media (min-width:1200px){.fhnjmd{grid-template-areas:'nav content void';grid-template-columns:1fr 85ch 1fr;padding:1rem;max-width:150ch;margin:0 auto;}}/*!sc*/
data-styled.g21[id="default__Grid-cc4rlb-0"]{content:"fhnjmd,"}/*!sc*/
.giaaSE{grid-area:nav;}/*!sc*/
data-styled.g22[id="default__NavigationSlot-cc4rlb-1"]{content:"giaaSE,"}/*!sc*/
.hVUruk{grid-area:content;}/*!sc*/
data-styled.g23[id="default__Content-cc4rlb-2"]{content:"hVUruk,"}/*!sc*/
.iBPGgH{display:grid;grid-template-areas:'next' 'prev';}/*!sc*/
@media (min-width:576px){.iBPGgH{grid-template-areas:'prev void next';grid-template-columns:auto 1fr auto;}}/*!sc*/
data-styled.g24[id="default__Paging-cc4rlb-3"]{content:"iBPGgH,"}/*!sc*/
.bDSAqh{grid-area:prev;}/*!sc*/
data-styled.g25[id="default__StyledPrev-cc4rlb-4"]{content:"bDSAqh,"}/*!sc*/
.dmuBWa{grid-area:next;justify-self:flex-end;}/*!sc*/
data-styled.g26[id="default__StyledNext-cc4rlb-5"]{content:"dmuBWa,"}/*!sc*/
Routing#
Why?#
- navigating makes the page reload
- without caching it can be slow
- avoid page reloads by using a router
How?#
Using react-router#
- the following is just an overview, the docs are more detailed
Router#
examples use a custom Router based on MemoryRouter
Route#
- docs
- matches
path to components - multiple can be active
- can be nested, side-by-side
- fully dynamic
- can have params
/some/route/:param
Switch#
- docs
- ensures that only one
Route is active at a time - use for fallback (404) routes
Link#
- docs
- replaces
a tags to avoid reloads NavLink can be used to apply “active styles” docs
Redirect#
- docs
- when rendered, redirect to
to prop - use it to keep old links working
useParams#
- docs
- get hold of params in your components
Simple#
import React, { FC } from 'react'
import { Route, Switch } from 'react-router'
import { Link } from 'react-router-dom'
export const Simple: FC = () => {
return (
<Switch>
<Route path="/lorem">lorem</Route>
<Route path="/ipsum">ipsum</Route>
<Route path="/dolor">dolor</Route>
<Route path="/">
<h1>Home</h1>
<ul>
<li>
<Link to="/lorem">lorem</Link>
</li>
<li>
<Link to="/ipsum">ipsum</Link>
</li>
<li>
<Link to="/dolor">dolor</Link>
</li>
</ul>
</Route>
</Switch>
)
}
export default <Simple />
404 Page#
import React, { FC } from 'react'
import { NavLink, Route, Switch } from 'react-router-dom'
import classes from './example.module.css'
export const NavBar: FC = () => {
return (
<nav>
<NavLink to="/" exact activeClassName={classes.activeLink}>
home
</NavLink>
{' '}
<NavLink to="/pricing" activeClassName={classes.activeLink}>
pricing
</NavLink>
{' '}
<NavLink to="/about" activeClassName={classes.activeLink}>
about
</NavLink>
{' '}
<NavLink
to="/this-page-does-not-exist"
activeClassName={classes.activeLink}
>
broken link
</NavLink>
</nav>
)
}
export const Example: FC = () => {
return (
<div>
<NavBar />
<article>
<Switch>
<Route path="/pricing">pricing page</Route>
<Route path="/about">about page</Route>
<Route path="/" exact>
home page
</Route>
<Route path="/">404 page</Route>
</Switch>
</article>
</div>
)
}
export default <Example />
Using Params#
import React, { FC } from 'react'
import { Redirect, Route, Switch, useParams } from 'react-router'
import { Link } from 'react-router-dom'
import { Database } from './database'
export const Article: FC = () => {
const { articleId } = useParams<{ articleId: string }>()
const article = Database.getArticleById(Number(articleId))
const user = article && Database.getUserById(article.owner)
return (
<div>
{user && article ? (
<div>
<h1>{article.title}</h1>
<p>{article.content}</p>
<Link to={`/user/${user.id}`}>
<i>by {user.name}</i>
</Link>
</div>
) : (
<h1>Cannot find article</h1>
)}
</div>
)
}
export const User: FC = () => {
const { userId } = useParams<{ userId: string }>()
const user = Database.getUserById(userId)
const articles = user ? user.articles.map(Database.getArticleById) : []
return (
<div>
{user ? (
<div>
<h1>Posts from {user.name}</h1>
{articles.length ? (
<ul>
{articles.map((article) => {
if (!article) throw new Error()
const { title, id } = article
return (
<li key={id}>
<Link to={`/article/${id}`}>{title}</Link>
</li>
)
})}
</ul>
) : (
<p>{user.name} has no articles</p>
)}
</div>
) : (
<h1>Cannot find user with id {userId}</h1>
)}
</div>
)
}
export const Users: FC = () => {
const users = Database.getUsers()
return (
<div>
<h1>Users</h1>
<ul>
{users.map(({ id, name }) => (
<li key={id}>
<Link to={`/user/${id}`}>{name}</Link>
</li>
))}
</ul>
</div>
)
}
export const Params: FC = () => {
return (
<Switch>
<Route path="/users">
<Users />
</Route>
<Route path="/user/:userId">
<User />
</Route>
<Route path="/article/:articleId">
<Article />
</Route>
<Route path="/">
<Redirect to="/users" />
</Route>
</Switch>
)
}
export default <Params />