React Tapas 6: Router part 2
Some missing pieces of Router from latest session:
1. Link #
To add links from one page to another we can't use <a>
directly because it triggers a new page reload. A <Link>
convenience component is provided from react-router library:
const HomePage = () => {
return (
<div>
<Link to="/about">About us</Link>
</div>
)
}
2. Route params #
We can define route params in the router using the :param
syntaxis:
const Router = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="posts">
<PostListPage />
</Route>
<Route exact path="post/:id">
<PostDetailPage />
</Route>
</Switch>
</BrowserRouter>
)
}
We can access the parameters using the "useParams" hook, that returns an object with all parameters:
const PostDetailPage = () => {
const params = useParams()
return (
<div>
<h1>Post id: {params.id}</h1>
</div>
)
}
Notice that, with typescript, we need it's better to type the parameters:
const params = useParams<{ id: string }>()
3. Imperative API #
Sometimes (almost never) we need to change the history directly (without using Link(s)). For example, navigating when pressing a button (a bad practice, by the way).
For those scenarios, we can use "useHistory" hook:
const HomePage = () => {
const history = useHistory();
return (
<button onClick={ () => history.push('/about') }>
Visit about
</button>
)
}
4. Redirects #
It's tempting to use the imperative API to make page redirects.
Use
const PostDetailPage = () => {
const user = useCurrentUser();
if (!user) return <Redirect to="/login" />
return <div>Only visible if there's a user session</div>
}
5. Add a footer to a layout #
Just pass the footer to the Layout in props:
const Layout = ({ title, children, footer }) => {
return (
<div>
<header>
<h1>{title || 'Sin título'}</h1>
</header>
{children && <main>{children}</main>}
{footer && <footer>{footer}</footer>}
</div>
)
}
Usage:
const AboutPage = () => (
<Layout title="About" footer={<div>Búscanos en twitch</div>}>
Hola
</Layout>
)
Corollary: The most difficult of React dev is not to over-engineer.
Note: What React renders #
the following line:
{children && <main>{children}</main>}
means: "if there's children, render it (wrapped by a main)".
It is almost equivalent to:
{children ? <main>{children}</main> : null}
"if theres a children, render it (wrapped by a main), otherwise render nothing"
This work because React does not render when it receives null, undefined or false.
You have to be careful, tho.
For example:
{list.length && <ul>...</ul>}
This will render a "0" if the list is empty.
There are two alternatives:
{list.length > 0 && <ul>...</ul>}
or:
{list.length ? <ul>...</ul> : null}
By the way, Kent recommends not to use &&. I disagree (I think is easier to read than ternary and more concise. But is good to know the problems)