1629600360
Dans cette vidéo je vous propose de découvrir ensemble ce qu'est [Next.js](https://nextjs.org/) et de voir les différents types de rendu possibles.
1626607980
This in the first video in my NextJS framework crash course series! NextJS is a javascript framework that lets you build server-side rendering and static web applications using React. In this video, I go over the course outline! If you are excited for this course please like, subscribe, and turn on notifications! It helps me out so much!
Social media dashboard GitHub: https://github.com/bjcarlson42/nextjs-social-dashboard
NextJS website: https://nextjs.org/
(0:00) Introduction
(0:31) Going over entire course!
NextJS Crash Course Video Outline:
Playlist: https://www.youtube.com/playlist?list=PLL1pJgYmqo2vYtT0v_7axfIG86fyL1whf
Course Intro - https://youtu.be/_dqkETqCJXQ ⬅️⬅️⬅️ You are here
What is Next.js? - https://youtu.be/L8RaJZodkv8
Pages, CSS, Static Files - https://youtu.be/HM5kB2x1ccw
getInitialProps - https://youtu.be/RgQxcw2R1q0
getStaticProps - https://youtu.be/VH_3hzpAPbQ
getStaticPaths - https://youtu.be/nKg0132Nu0o
getServerSideProps - https://youtu.be/qUhYZi-KMPQ
YouTube API - https://youtu.be/jVc8qVq0NR8
GitHub API - https://youtu.be/4g3Ziy20quY
Strava API - https://youtu.be/fNOUHccIchU
Deploying On Vercel - https://youtu.be/ben3vRAqvKE
✍️ Join my newsletter!! https://buttondown.email/benjamincarlson ✍️
I send out one email the first day of every month with new YouTube videos, Medium posts, stuff I’ve been working on, and anything else programming related I’ve found interesting.
#nextjs
#nextjs #next #javascipt #nextjs course introduction
1652595840
Breadcrumbs are a website navigation tool that allows a user to see their current page's "stack" of how it is nested under any parent pages. Users can then jump back to a parent page by clicking the associated breadcrumb link. These "Crumbs" increase the User Experience of the application, making it easier for the users to navigate nested pages efficiently and effectively.
Breadcrumbs are popular enough that if you are building a web dashboard or application, you may have considered adding them. Generating these breadcrumb links efficiently and with the appropriate context is key to an improved user experience.
Let's build a smart NextBreadcrumbs
React component that will parse the current route and build a dynamic breadcrumbs display that can handle both static & dynamic routes efficiently.
My projects usually revolve around Nextjs and MUI (formerly Material-UI) so that is the angle that I am going to approach this problem from, although the solution should work for any Nextjs-related application.
To start, our NextBreadcrumbs
component will only handle static routes, meaning that our project has only static pages defined in the pages
directory.
The following are examples of static routes because they do not contain [
s and ]
s in the route names, meaning the directory structure lines up 1:1 exactly with the expected URLs that they serve.
pages/index.js
--> /
pages/about.js
--> /about
pages/my/super/nested/route.js
--> /my/super/nested/route
The solution will be extended to handle dynamic routes later.
We can start with the basic component that uses the MUI Breadcrumbs
component as a baseline.
import Breadcrumbs from '@mui/material/Breadcrumbs';
import * as React from 'react';
export default function NextBreadcrumbs() {
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
The above creates the basic structure of the NextBreadcrumbs
React component, imports the correct dependencies, and renders an empty Breadcrumbs
MUI component.
We can then add in the next/router
hooks, which will allow us to build the breadcrumbs from the current route.
We also create a Crumb
component that will be used to render each link. This is a pretty dumb component for now, except that it will render normal text instead of a link for the last breadcrumb.
In a situation like /settings/notifications
, it would render as the following:
Home (/ link) > Settings (/settings link) > Notifications (no link)
This is because the user is already on the last breadcrumb's page, so there is no need to link out to the same page. All the other crumbs are rendered as links to be clicked.
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Link from '@mui/material/Link';
import Typography from '@mui/material/Typography';
import { useRouter } from 'next/router';
import React from 'react';
export default function NextBreadcrumbs() {
// Gives us ability to load the current route details
const router = useRouter();
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
// Each individual "crumb" in the breadcrumbs list
function Crumb({ text, href, last=false }) {
// The last crumb is rendered as normal text since we are already on the page
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
// All other crumbs will be rendered as links that can be visited
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
With this layout, we can then dive back into the NextBreadcrumbs
component to generate the breadcrumbs from the route. Some existing code will start to be omitted to keep the code pieces smaller. The full example is shown below.
We will generate a list of breadcrumb objects that contain the information to be rendered by each Crumb
element. Each breadcrumb will be created by parsing the Nextjs router's asPath
property, which is a string containing the route as shown in the browser URL bar.
We will strip any query parameters, such as ?query=value
, from the URL to make the breadcrumb creation process more straightforward.
export default function NextBreadcrumbs() {
// Gives us ability to load the current route details
const router = useRouter();
function generateBreadcrumbs() {
// Remove any query parameters, as those aren't included in breadcrumbs
const asPathWithoutQuery = router.asPath.split("?")[0];
// Break down the path between "/"s, removing empty entities
// Ex:"/my/nested/path" --> ["my", "nested", "path"]
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
// Iterate over the list of nested route parts and build
// a "crumb" object for each one.
const crumblist = asPathParts.map((subpath, idx) => {
// We can get the partial nested route for the crumb
// by joining together the path parts up to this point.
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
// The title will just be the route string for now
const title = subpath;
return { href, text };
})
// Add in a default "Home" crumb for the top-level
return [{ href: "/", text: "Home" }, ...crumblist];
}
// Call the function to generate the breadcrumbs list
const breadcrumbs = generateBreadcrumbs();
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
With this list of breadcrumbs, we can now render them using the Breadcrumbs
and Crumb
components. As previously mentioned, only the return
portion of our component is shown for brevity.
// ...rest of NextBreadcrumbs component above...
return (
{/* The old breadcrumb ending with '/>' was converted into this */}
<Breadcrumbs aria-label="breadcrumb">
{/*
Iterate through the crumbs, and render each individually.
We "mark" the last crumb to not have a link.
*/}
{breadcrumbs.map((crumb, idx) => (
<Crumb {...crumb} key={idx} last={idx === breadcrumbs.length - 1} />
))}
</Breadcrumbs>
);
This should start generating some very basic - but working - breadcrumbs on our site once rendered; /user/settings/notifications
would render as
Home > user > settings > notifications
There is a quick improvement that we can make before going further though. Right now the breadcrumb list is recreated every time the component re-renders, so we can memoize the crumb list for a given route to save some performance. To accomplish this, we can wrap our generateBreadcrumbs
function call in the useMemo
React hook.
const router = useRouter();
// this is the same "generateBreadcrumbs" function, but placed
// inside a "useMemo" call that is dependent on "router.asPath"
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathWithoutQuery = router.asPath.split("?")[0];
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
const crumblist = asPathParts.map((subpath, idx) => {
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return { href, text: subpath };
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath]);
return // ...rest below...
Before we start incorporating dynamic routes, we can clean this current solution up more by including a nice way to change the text shown for each crumb generated.
Right now, if we have a path like /user/settings/notifications
, then it will show:
Home > user > settings > notifications
which is not very appealing. We can provide a function to the NextBreadcrumbs
component that will try to generate a more user-friendly name for each of these nested route crumbs.
const _defaultGetDefaultTextGenerator= path => path
export default function NextBreadcrumbs({ getDefaultTextGenerator=_defaultGetDefaultTextGenerator }) {
const router = useRouter();
// Two things of importance:
// 1. The addition of getDefaultTextGenerator in the useMemo dependency list
// 2. getDefaultTextGenerator is now being used for building the text property
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathWithoutQuery = router.asPath.split("?")[0];
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
const crumblist = asPathParts.map((subpath, idx) => {
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return { href, text: getDefaultTextGenerator(subpath, href) };
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, getDefaultTextGenerator]);
return ( // ...rest below
and then our parent component can have something like the following, to title-ize the subpaths, or maybe even replace them with a new string.
{/* Assume that `titleize` is written and works appropriately */}
<NextBreadcrumbs getDefaultTextGenerator={path => titleize(path)} />
This implementation would then result in the following breadcrumbs. The full code example at the bottom has more examples of this.
Home > User > Settings > Notifications
Nextjs's router allows for including dynamic routes that uses Pattern Matching to allow for URLs to have slugs, UUIDs, and other dynamic values that will then be passed to your views.
For example, if your Nextjs application has a page component at pages/post/[post_id].js
, then the routes /post/1
and /post/abc
will match it.
For our breadcrumbs component, we would like to show the name of the associated post instead of just its UUID. This means that the component will need to dynamically look up the post data based on the nested URL route path and regenerate the text of the associated crumb.
Right now, if you visit /post/abc
, you would see breadcrumbs that look like
post > abc
but if the post with UUID has a title of My First Post
, then we want to change the breadcrumbs to say
post > My First Post
Let's dive into how that can happen using async
functions.
asPath
vs pathname
The next/router
router instance in our code has two useful properties for our NextBreadcrumbs
component; asPath
and pathname
. The router asPath
is the URL path as shown directly in the URL bar of the browser. The pathname
is a more internal version of the URL that has the dynamic parts of the path replaced with their [parameter]
components.
For example, consider the path /post/abc
from above.
The asPath
would be /post/abc
as the URL is shown
The pathname
would be /post/[post_id]
as our pages
directory dictates
We can use these two URL path variants to build a way to dynamically fetch information about the breadcrumb, so we can show more contextually appropriate information to the user.
There is a lot going on below, so please re-read it - and the helpful notes below it - a few times over if needed.
const _defaultGetTextGenerator = (param, query) => null;
const _defaultGetDefaultTextGenerator = path => path;
// Pulled out the path part breakdown because its
// going to be used by both `asPath` and `pathname`
const generatePathParts = pathStr => {
const pathWithoutQuery = pathStr.split("?")[0];
return pathWithoutQuery.split("/")
.filter(v => v.length > 0);
}
export default function NextBreadcrumbs({
getTextGenerator=_defaultGetTextGenerator,
getDefaultTextGenerator=_defaultGetDefaultTextGenerator
}) {
const router = useRouter();
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathNestedRoutes = generatePathParts(router.asPath);
const pathnameNestedRoutes = generatePathParts(router.pathname);
const crumblist = asPathParts.map((subpath, idx) => {
// Pull out and convert "[post_id]" into "post_id"
const param = pathnameNestedRoutes[idx].replace("[", "").replace("]", "");
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return {
href, textGenerator: getTextGenerator(param, router.query),
text: getDefaultTextGenerator(subpath, href)
};
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, router.pathname, router.query, getTextGenerator, getDefaultTextGenerator]);
return ( // ...rest below
The asPath
breakdown was moved to a generatePathParts
function since the same logic is used for both router.asPath
and router.pathname
.
Determine the param
eter that lines up with the dynamic route value, so abc
would result in post_id
.
The nested route param
eter and all associated query values (router.query
) are passed to a provided getTextGenerator
which will return either a null
value or a Promise
response that should return the dynamic string to use in the associated breadcrumb.
The useMemo
dependency array has more dependencies added; router.pathname
, router.query
, and getTextGenerator
.
Finally, we need to update the Crumb
component to use this textGenerator
value if it is provided for the associated crumb object.
function Crumb({ text: defaultText, textGenerator, href, last=false }) {
const [text, setText] = React.useState(defaultText);
useEffect(async () => {
// If `textGenerator` is nonexistent, then don't do anything
if (!Boolean(textGenerator)) { return; }
// Run the text generator and set the text again
const finalText = await textGenerator();
setText(finalText);
}, [textGenerator]);
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
The breadcrumbs can now handle both static routes and dynamic routes cleanly with the potential to display user-friendly values. While the above code is the business logic of the component, this can all be used with a parent component that looks like the final example below.
// NextBreadcrumbs.js
const _defaultGetTextGenerator = (param, query) => null;
const _defaultGetDefaultTextGenerator = path => path;
// Pulled out the path part breakdown because its
// going to be used by both `asPath` and `pathname`
const generatePathParts = pathStr => {
const pathWithoutQuery = pathStr.split("?")[0];
return pathWithoutQuery.split("/")
.filter(v => v.length > 0);
}
export default function NextBreadcrumbs({
getTextGenerator=_defaultGetTextGenerator,
getDefaultTextGenerator=_defaultGetDefaultTextGenerator
}) {
const router = useRouter();
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathNestedRoutes = generatePathParts(router.asPath);
const pathnameNestedRoutes = generatePathParts(router.pathname);
const crumblist = asPathParts.map((subpath, idx) => {
// Pull out and convert "[post_id]" into "post_id"
const param = pathnameNestedRoutes[idx].replace("[", "").replace("]", "");
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return {
href, textGenerator: getTextGenerator(param, router.query),
text: getDefaultTextGenerator(subpath, href)
};
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, router.pathname, router.query, getTextGenerator, getDefaultTextGenerator]);
return (
<Breadcrumbs aria-label="breadcrumb">
{breadcrumbs.map((crumb, idx) => (
<Crumb {...crumb} key={idx} last={idx === breadcrumbs.length - 1} />
))}
</Breadcrumbs>
);
}
function Crumb({ text: defaultText, textGenerator, href, last=false }) {
const [text, setText] = React.useState(defaultText);
useEffect(async () => {
// If `textGenerator` is nonexistent, then don't do anything
if (!Boolean(textGenerator)) { return; }
// Run the text generator and set the text again
const finalText = await textGenerator();
setText(finalText);
}, [textGenerator]);
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
and then an example of this NextBreadcrumbs
being used can be seen below. Note that useCallback
is used to create only one reference to each helper function which will prevent unnecessary re-renders of the breadcrumbs when/if the page layout component re-rendered. You could also move this out to the top-level scope of the file, but I don't like to pollute the global scope like that.
// MyPage.js (Parent Component)
import React from 'react';
import NextBreadcrumbs from "./NextBreadcrumbs";
function MyPageLayout() {
// Either lookup a nice label for the subpath, or just titleize it
const getDefaultTextGenerator = React.useCallback((subpath) => {
return {
"post": "Posts",
"settings": "User Settings",
}[subpath] || titleize(subpath);
}, [])
// Assuming `fetchAPI` loads data from the API and this will use the
// parameter name to determine how to resolve the text. In the example,
// we fetch the post from the API and return it's `title` property
const getTextGenerator = React.useCallback((param, query) => {
return {
"post_id": () => await fetchAPI(`/posts/${query.post_id}/`).title,
}[param];
}, []);
return () {
<div>
{/* ...Whatever else... */}
<NextBreadcrumbs
getDefaultTextGenerator={getDefaultTextGenerator}
getTextGenerator={getTextGenerator}
/>
{/* ...Whatever else... */}
</div>
}
}
This is one of my more in-depth and technical posts, so I hope you enjoyed it, and please comment or reach out so that I can ensure consistency and correctness. Hopefully, this post taught you a few strategies or concepts about Nextjs.
Source: https://hackernoon.com/implement-a-dynamic-breadcrumb-in-reactnextjs
1652517446
Las migas de pan son una herramienta de navegación del sitio web que permite a un usuario ver la "pila" de su página actual de cómo está anidada debajo de las páginas principales. Luego, los usuarios pueden regresar a una página principal haciendo clic en el enlace de ruta de navegación asociado. Estas "migajas" aumentan la experiencia del usuario de la aplicación, lo que facilita que los usuarios naveguen por páginas anidadas de manera eficiente y efectiva.
Las migas de pan son lo suficientemente populares como para que, si está creando un panel de control web o una aplicación, haya considerado agregarlas. Generar estos enlaces de migas de pan de manera eficiente y con el contexto apropiado es clave para una experiencia de usuario mejorada.
Construyamos un NextBreadcrumbs
componente React inteligente que analice la ruta actual y construya una pantalla de migas de pan dinámicas que pueda manejar rutas tanto estáticas como dinámicas de manera eficiente.
Mis proyectos generalmente giran en torno a Nextjs y MUI (anteriormente Material-UI), por lo que ese es el ángulo desde el que abordaré este problema, aunque la solución debería funcionar para cualquier aplicación relacionada con Nextjs.
Para empezar, nuestro NextBreadcrumbs
componente solo manejará rutas estáticas, lo que significa que nuestro proyecto solo tiene páginas estáticas definidas en el pages
directorio.
Los siguientes son ejemplos de rutas estáticas porque no contienen [
s y ]
s en los nombres de ruta, lo que significa que la estructura del directorio se alinea 1:1 exactamente con las URL esperadas que sirven.
pages/index.js
-->/
pages/about.js
-->/about
pages/my/super/nested/route.js
-->/my/super/nested/route
La solución se ampliará para manejar rutas dinámicas más adelante.
Podemos comenzar con el componente básico que usa el componente MUIBreadcrumbs
como línea de base.
import Breadcrumbs from '@mui/material/Breadcrumbs';
import * as React from 'react';
export default function NextBreadcrumbs() {
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
Lo anterior crea la estructura básica del NextBreadcrumbs
componente React, importa las dependencias correctas y genera un Breadcrumbs
componente MUI vacío.
Luego podemos agregar los next/router
ganchos, lo que nos permitirá construir las migas de pan a partir de la ruta actual.
También creamos un Crumb
componente que se usará para representar cada enlace. Este es un componente bastante tonto por ahora, excepto que mostrará texto normal en lugar de un enlace para la última ruta de navegación.
En una situación como /settings/notifications
, se representaría de la siguiente manera:
Home (/ link) > Settings (/settings link) > Notifications (no link)
Esto se debe a que el usuario ya está en la última página de migas de pan, por lo que no es necesario vincular a la misma página. Todas las demás migajas se representan como enlaces en los que se puede hacer clic.
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Link from '@mui/material/Link';
import Typography from '@mui/material/Typography';
import { useRouter } from 'next/router';
import React from 'react';
export default function NextBreadcrumbs() {
// Gives us ability to load the current route details
const router = useRouter();
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
// Each individual "crumb" in the breadcrumbs list
function Crumb({ text, href, last=false }) {
// The last crumb is rendered as normal text since we are already on the page
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
// All other crumbs will be rendered as links that can be visited
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
Con este diseño, podemos volver a sumergirnos en el NextBreadcrumbs
componente para generar las migas de pan a partir de la ruta. Parte del código existente comenzará a omitirse para mantener las piezas de código más pequeñas. El ejemplo completo se muestra a continuación.
Generaremos una lista de objetos de migas de pan que contienen la información que cada Crumb
elemento debe representar. Cada ruta de navegación se creará analizando la propiedad del enrutador NextjsasPath
, que es una cadena que contiene la ruta como se muestra en la barra de URL del navegador.
Quitaremos todos los parámetros de consulta, como ?query=value
, de la URL para que el proceso de creación de la ruta de navegación sea más sencillo.
export default function NextBreadcrumbs() {
// Gives us ability to load the current route details
const router = useRouter();
function generateBreadcrumbs() {
// Remove any query parameters, as those aren't included in breadcrumbs
const asPathWithoutQuery = router.asPath.split("?")[0];
// Break down the path between "/"s, removing empty entities
// Ex:"/my/nested/path" --> ["my", "nested", "path"]
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
// Iterate over the list of nested route parts and build
// a "crumb" object for each one.
const crumblist = asPathParts.map((subpath, idx) => {
// We can get the partial nested route for the crumb
// by joining together the path parts up to this point.
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
// The title will just be the route string for now
const title = subpath;
return { href, text };
})
// Add in a default "Home" crumb for the top-level
return [{ href: "/", text: "Home" }, ...crumblist];
}
// Call the function to generate the breadcrumbs list
const breadcrumbs = generateBreadcrumbs();
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
Con esta lista de migas de pan, ahora podemos renderizarlas usando los componentes Breadcrumbs
y . Crumb
Como se mencionó anteriormente, solo return
se muestra la parte de nuestro componente por brevedad.
// ...rest of NextBreadcrumbs component above...
return (
{/* The old breadcrumb ending with '/>' was converted into this */}
<Breadcrumbs aria-label="breadcrumb">
{/*
Iterate through the crumbs, and render each individually.
We "mark" the last crumb to not have a link.
*/}
{breadcrumbs.map((crumb, idx) => (
<Crumb {...crumb} key={idx} last={idx === breadcrumbs.length - 1} />
))}
</Breadcrumbs>
);
Esto debería comenzar a generar algunas migas de pan muy básicas, pero que funcionan, en nuestro sitio una vez renderizado; /user/settings/notifications
representaría como
Home > user > settings > notifications
Sin embargo, hay una mejora rápida que podemos hacer antes de seguir adelante. En este momento, la lista de migas de pan se recrea cada vez que el componente se vuelve a renderizar, por lo que podemos memorizar la lista de migas de una ruta determinada para ahorrar algo de rendimiento. Para lograr esto, podemos envolver nuestra generateBreadcrumbs
llamada de función en el useMemo
gancho React.
const router = useRouter();
// this is the same "generateBreadcrumbs" function, but placed
// inside a "useMemo" call that is dependent on "router.asPath"
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathWithoutQuery = router.asPath.split("?")[0];
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
const crumblist = asPathParts.map((subpath, idx) => {
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return { href, text: subpath };
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath]);
return // ...rest below...
Antes de comenzar a incorporar rutas dinámicas, podemos limpiar más esta solución actual al incluir una forma agradable de cambiar el texto que se muestra para cada migaja generada.
En este momento, si tenemos una ruta como /user/settings/notifications
, se mostrará:
Home > user > settings > notifications
que no es muy atractivo. Podemos proporcionar una función al NextBreadcrumbs
componente que intentará generar un nombre más fácil de usar para cada uno de estos fragmentos de ruta anidados.
const _defaultGetDefaultTextGenerator= path => path
export default function NextBreadcrumbs({ getDefaultTextGenerator=_defaultGetDefaultTextGenerator }) {
const router = useRouter();
// Two things of importance:
// 1. The addition of getDefaultTextGenerator in the useMemo dependency list
// 2. getDefaultTextGenerator is now being used for building the text property
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathWithoutQuery = router.asPath.split("?")[0];
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
const crumblist = asPathParts.map((subpath, idx) => {
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return { href, text: getDefaultTextGenerator(subpath, href) };
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, getDefaultTextGenerator]);
return ( // ...rest below
y luego nuestro componente principal puede tener algo como lo siguiente, para titular las rutas secundarias, o tal vez incluso reemplazarlas con una nueva cadena.
{/* Assume that `titleize` is written and works appropriately */}
<NextBreadcrumbs getDefaultTextGenerator={path => titleize(path)} />
Esta implementación daría como resultado las siguientes migas de pan. El ejemplo de código completo en la parte inferior tiene más ejemplos de esto.
Home > User > Settings > Notifications
El enrutador de Nextjs permite incluir rutas dinámicas que usan Pattern Matching para permitir que las URL tengan slugs, UUID y otros valores dinámicos que luego se pasarán a sus vistas.
Por ejemplo, si su aplicación Nextjs tiene un componente de página en pages/post/[post_id].js
, las rutas /post/1
y /post/abc
coincidirán con él.
Para nuestro componente de migas de pan, nos gustaría mostrar el nombre de la publicación asociada en lugar de solo su UUID. Esto significa que el componente deberá buscar dinámicamente los datos de la publicación en función de la ruta de la ruta URL anidada y regenerar el texto de la migaja asociada.
En este momento, si visitas /post/abc
, verás migas de pan que parecen
post > abc
pero si la publicación con UUID tiene un título de My First Post
, entonces queremos cambiar las migas de pan para decir
post > My First Post
Profundicemos en cómo puede suceder eso usando async
funciones.
asPath
vspathname
La next/router
instancia del enrutador en nuestro código tiene dos propiedades útiles para nuestro NextBreadcrumbs
componente; asPath
y pathname
. El enrutador asPath
es la ruta URL como se muestra directamente en la barra de URL del navegador. Es pathname
una versión más interna de la URL que tiene las partes dinámicas de la ruta reemplazadas por sus [parameter]
componentes.
Por ejemplo, considere el camino /post/abc
desde arriba.
El asPath
sería /post/abc
como se muestra la URL
El pathname
sería como dicta /post/[post_id]
nuestro directoriopages
Podemos usar estas dos variantes de ruta de URL para crear una forma de obtener información dinámicamente sobre la ruta de navegación, de modo que podamos mostrar información contextualmente más apropiada para el usuario.
Están sucediendo muchas cosas a continuación, así que vuelva a leerlo, y las notas útiles a continuación, unas cuantas veces si es necesario.
const _defaultGetTextGenerator = (param, query) => null;
const _defaultGetDefaultTextGenerator = path => path;
// Pulled out the path part breakdown because its
// going to be used by both `asPath` and `pathname`
const generatePathParts = pathStr => {
const pathWithoutQuery = pathStr.split("?")[0];
return pathWithoutQuery.split("/")
.filter(v => v.length > 0);
}
export default function NextBreadcrumbs({
getTextGenerator=_defaultGetTextGenerator,
getDefaultTextGenerator=_defaultGetDefaultTextGenerator
}) {
const router = useRouter();
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathNestedRoutes = generatePathParts(router.asPath);
const pathnameNestedRoutes = generatePathParts(router.pathname);
const crumblist = asPathParts.map((subpath, idx) => {
// Pull out and convert "[post_id]" into "post_id"
const param = pathnameNestedRoutes[idx].replace("[", "").replace("]", "");
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return {
href, textGenerator: getTextGenerator(param, router.query),
text: getDefaultTextGenerator(subpath, href)
};
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, router.pathname, router.query, getTextGenerator, getDefaultTextGenerator]);
return ( // ...rest below
El asPath
desglose se movió a una generatePathParts
función ya que se usa la misma lógica para ambos router.asPath
y router.pathname
.
Determine el param
éter que se alinea con el valor de la ruta dinámica, por lo que abc
daría como resultado post_id
.
El éter de ruta anidado param
y todos los valores de consulta asociados ( router.query
) se pasan a un proveedor getTextGenerator
que devolverá un null
valor o una Promise
respuesta que debería devolver la cadena dinámica para usar en la ruta de navegación asociada.
La useMemo
matriz de dependencia tiene más dependencias agregadas; router.pathname
, router.query
y getTextGenerator
.
Finalmente, necesitamos actualizar el Crumb
componente para usar este textGenerator
valor si se proporciona para el objeto migas asociado.
function Crumb({ text: defaultText, textGenerator, href, last=false }) {
const [text, setText] = React.useState(defaultText);
useEffect(async () => {
// If `textGenerator` is nonexistent, then don't do anything
if (!Boolean(textGenerator)) { return; }
// Run the text generator and set the text again
const finalText = await textGenerator();
setText(finalText);
}, [textGenerator]);
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
Las migas de pan ahora pueden manejar rutas estáticas y rutas dinámicas de forma limpia con el potencial de mostrar valores fáciles de usar. Si bien el código anterior es la lógica comercial del componente, todo esto se puede usar con un componente principal que se parece al ejemplo final a continuación.
// NextBreadcrumbs.js
const _defaultGetTextGenerator = (param, query) => null;
const _defaultGetDefaultTextGenerator = path => path;
// Pulled out the path part breakdown because its
// going to be used by both `asPath` and `pathname`
const generatePathParts = pathStr => {
const pathWithoutQuery = pathStr.split("?")[0];
return pathWithoutQuery.split("/")
.filter(v => v.length > 0);
}
export default function NextBreadcrumbs({
getTextGenerator=_defaultGetTextGenerator,
getDefaultTextGenerator=_defaultGetDefaultTextGenerator
}) {
const router = useRouter();
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathNestedRoutes = generatePathParts(router.asPath);
const pathnameNestedRoutes = generatePathParts(router.pathname);
const crumblist = asPathParts.map((subpath, idx) => {
// Pull out and convert "[post_id]" into "post_id"
const param = pathnameNestedRoutes[idx].replace("[", "").replace("]", "");
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return {
href, textGenerator: getTextGenerator(param, router.query),
text: getDefaultTextGenerator(subpath, href)
};
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, router.pathname, router.query, getTextGenerator, getDefaultTextGenerator]);
return (
<Breadcrumbs aria-label="breadcrumb">
{breadcrumbs.map((crumb, idx) => (
<Crumb {...crumb} key={idx} last={idx === breadcrumbs.length - 1} />
))}
</Breadcrumbs>
);
}
function Crumb({ text: defaultText, textGenerator, href, last=false }) {
const [text, setText] = React.useState(defaultText);
useEffect(async () => {
// If `textGenerator` is nonexistent, then don't do anything
if (!Boolean(textGenerator)) { return; }
// Run the text generator and set the text again
const finalText = await textGenerator();
setText(finalText);
}, [textGenerator]);
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
y luego se puede ver un ejemplo de este NextBreadcrumbs
uso a continuación. Tenga en cuenta que useCallback
se utiliza para crear solo una referencia a cada función auxiliar, lo que evitará que se vuelvan a procesar innecesariamente las migas de pan cuando/si el componente de diseño de página se vuelve a procesar. También puede mover esto al alcance de nivel superior del archivo, pero no me gusta contaminar el alcance global de esa manera.
// MyPage.js (Parent Component)
import React from 'react';
import NextBreadcrumbs from "./NextBreadcrumbs";
function MyPageLayout() {
// Either lookup a nice label for the subpath, or just titleize it
const getDefaultTextGenerator = React.useCallback((subpath) => {
return {
"post": "Posts",
"settings": "User Settings",
}[subpath] || titleize(subpath);
}, [])
// Assuming `fetchAPI` loads data from the API and this will use the
// parameter name to determine how to resolve the text. In the example,
// we fetch the post from the API and return it's `title` property
const getTextGenerator = React.useCallback((param, query) => {
return {
"post_id": () => await fetchAPI(`/posts/${query.post_id}/`).title,
}[param];
}, []);
return () {
<div>
{/* ...Whatever else... */}
<NextBreadcrumbs
getDefaultTextGenerator={getDefaultTextGenerator}
getTextGenerator={getTextGenerator}
/>
{/* ...Whatever else... */}
</div>
}
}
Esta es una de mis publicaciones más profundas y técnicas, así que espero que la hayas disfrutado, y por favor comenta o comunícate para que pueda garantizar la coherencia y la corrección. Con suerte, esta publicación le enseñó algunas estrategias o conceptos sobre Nextjs.
Fuente: https://hackernoon.com/implement-a-dynamic-breadcrumb-in-reactnextjs
1652517249
ブレッドクラムは、ユーザーが現在のページの「スタック」を、親ページの下にどのようにネストされているかを確認できるようにするWebサイトナビゲーションツールです。その後、ユーザーは関連するブレッドクラムリンクをクリックして、親ページに戻ることができます。これらの「クラム」は、アプリケーションのユーザーエクスペリエンスを向上させ、ユーザーがネストされたページを効率的かつ効果的にナビゲートしやすくします。
ブレッドクラムは十分に人気があるため、Webダッシュボードまたはアプリケーションを構築している場合は、それらを追加することを検討した可能性があります。これらのブレッドクラムリンクを効率的かつ適切なコンテキストで生成することは、ユーザーエクスペリエンスを向上させるための鍵です。
NextBreadcrumbs
現在のルートを解析し、静的ルートと動的ルートの両方を効率的に処理できる動的ブレッドクラム表示を構築するスマートReactコンポーネントを構築しましょう。
私のプロジェクトは通常、NextjsとMUI(以前のMaterial-UI)を中心に展開しているため、この問題に取り組む角度ですが、ソリューションはNextjs関連のアプリケーションでも機能するはずです。
まず、NextBreadcrumbs
コンポーネントは静的ルートのみを処理します。つまり、プロジェクトのpages
ディレクトリには静的ページのみが定義されています。
[
以下は静的ルートの例です。これは、ルート名にsとsが含まれていないためです]
。つまり、ディレクトリ構造は、提供される予想URLと正確に1:1で整列します。
pages/index.js
->/
pages/about.js
->/about
pages/my/super/nested/route.js
->/my/super/nested/route
ソリューションは、後で動的ルートを処理するように拡張されます。
MUIコンポーネントをベースラインとして使用する基本コンポーネントから始めることができますBreadcrumbs
。
import Breadcrumbs from '@mui/material/Breadcrumbs';
import * as React from 'react';
export default function NextBreadcrumbs() {
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
上記は、NextBreadcrumbs
Reactコンポーネントの基本構造を作成し、正しい依存関係をインポートして、空のBreadcrumbs
MUIコンポーネントをレンダリングします。
次に、フックを追加しますnext/router
。これにより、現在のルートからブレッドクラムを作成できます。
Crumb
また、各リンクのレンダリングに使用されるコンポーネントも作成します。これは、最後のブレッドクラムのリンクの代わりに通常のテキストをレンダリングすることを除いて、今のところかなりばかげたコンポーネントです。
のような状況/settings/notifications
では、次のようにレンダリングされます。
Home (/ link) > Settings (/settings link) > Notifications (no link)
これは、ユーザーがすでに最後のブレッドクラムのページにいるため、同じページにリンクする必要がないためです。他のすべてのパン粉は、クリックするリンクとしてレンダリングされます。
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Link from '@mui/material/Link';
import Typography from '@mui/material/Typography';
import { useRouter } from 'next/router';
import React from 'react';
export default function NextBreadcrumbs() {
// Gives us ability to load the current route details
const router = useRouter();
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
// Each individual "crumb" in the breadcrumbs list
function Crumb({ text, href, last=false }) {
// The last crumb is rendered as normal text since we are already on the page
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
// All other crumbs will be rendered as links that can be visited
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
このレイアウトを使用すると、NextBreadcrumbs
コンポーネントに戻ってルートからブレッドクラムを生成できます。一部の既存のコードは、コードの断片を小さく保つために省略され始めます。完全な例を以下に示します。
Crumb
各要素によってレンダリングされる情報を含むブレッドクラムオブジェクトのリストを生成します。各ブレッドクラムは、ブラウザのURLバーに表示されるルートを含む文字列であるNextjsルーターのプロパティを解析することによって作成されます。asPath
?query=value
ブレッドクラムの作成プロセスをより簡単にするために、URLなどのクエリパラメータをすべて削除します。
export default function NextBreadcrumbs() {
// Gives us ability to load the current route details
const router = useRouter();
function generateBreadcrumbs() {
// Remove any query parameters, as those aren't included in breadcrumbs
const asPathWithoutQuery = router.asPath.split("?")[0];
// Break down the path between "/"s, removing empty entities
// Ex:"/my/nested/path" --> ["my", "nested", "path"]
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
// Iterate over the list of nested route parts and build
// a "crumb" object for each one.
const crumblist = asPathParts.map((subpath, idx) => {
// We can get the partial nested route for the crumb
// by joining together the path parts up to this point.
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
// The title will just be the route string for now
const title = subpath;
return { href, text };
})
// Add in a default "Home" crumb for the top-level
return [{ href: "/", text: "Home" }, ...crumblist];
}
// Call the function to generate the breadcrumbs list
const breadcrumbs = generateBreadcrumbs();
return (
<Breadcrumbs aria-label="breadcrumb" />
);
}
このブレッドクラムのリストを使用して、Breadcrumbs
およびCrumb
コンポーネントを使用してそれらをレンダリングできるようになりました。前述のreturn
ように、簡潔にするために、コンポーネントの一部のみを示しています。
// ...rest of NextBreadcrumbs component above...
return (
{/* The old breadcrumb ending with '/>' was converted into this */}
<Breadcrumbs aria-label="breadcrumb">
{/*
Iterate through the crumbs, and render each individually.
We "mark" the last crumb to not have a link.
*/}
{breadcrumbs.map((crumb, idx) => (
<Crumb {...crumb} key={idx} last={idx === breadcrumbs.length - 1} />
))}
</Breadcrumbs>
);
これにより、レンダリングされたサイトで非常に基本的な(ただし機能する)ブレッドクラムの生成が開始されます。/user/settings/notifications
次のようにレンダリングされます
Home > user > settings > notifications
ただし、先に進む前に行うことができる迅速な改善があります。現在、コンポーネントが再レンダリングされるたびにブレッドクラムリストが再作成されるため、パフォーマンスを節約するために、特定のルートのクラムリストをメモ化できます。これを実現するために、generateBreadcrumbs
関数呼び出しをuseMemo
Reactフックでラップできます。
const router = useRouter();
// this is the same "generateBreadcrumbs" function, but placed
// inside a "useMemo" call that is dependent on "router.asPath"
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathWithoutQuery = router.asPath.split("?")[0];
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
const crumblist = asPathParts.map((subpath, idx) => {
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return { href, text: subpath };
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath]);
return // ...rest below...
動的ルートの組み込みを開始する前に、生成されたクラムごとに表示されるテキストを変更するための優れた方法を含めることで、この現在のソリューションをさらにクリーンアップできます。
現在、のようなパスがある場合は、次の/user/settings/notifications
ように表示されます。
Home > user > settings > notifications
これはあまり魅力的ではありません。NextBreadcrumbs
これらのネストされたルートクラムのそれぞれに対して、よりユーザーフレンドリーな名前を生成しようとする関数をコンポーネントに提供できます。
const _defaultGetDefaultTextGenerator= path => path
export default function NextBreadcrumbs({ getDefaultTextGenerator=_defaultGetDefaultTextGenerator }) {
const router = useRouter();
// Two things of importance:
// 1. The addition of getDefaultTextGenerator in the useMemo dependency list
// 2. getDefaultTextGenerator is now being used for building the text property
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathWithoutQuery = router.asPath.split("?")[0];
const asPathNestedRoutes = asPathWithoutQuery.split("/")
.filter(v => v.length > 0);
const crumblist = asPathParts.map((subpath, idx) => {
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return { href, text: getDefaultTextGenerator(subpath, href) };
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, getDefaultTextGenerator]);
return ( // ...rest below
次に、親コンポーネントは、サブパスにタイトルを付けるために、またはサブパスを新しい文字列に置き換えるために、次のようなものを持つことができます。
{/* Assume that `titleize` is written and works appropriately */}
<NextBreadcrumbs getDefaultTextGenerator={path => titleize(path)} />
この実装により、次のブレッドクラムが発生します。下部の完全なコード例には、この例がさらにあります。
Home > User > Settings > Notifications
Nextjsのルーターでは、パターンマッチングを使用して、URLにスラッグ、UUID、およびビューに渡されるその他の動的な値を含めることができる動的ルートを含めることができます。
たとえば、Nextjsアプリケーションのにページコンポーネントがあるpages/post/[post_id].js
場合、ルート/post/1
と/post/abc
はそれに一致します。
ブレッドクラムコンポーネントでは、UUIDだけでなく、関連付けられた投稿の名前を表示したいと思います。これは、コンポーネントがネストされたURLルートパスに基づいて投稿データを動的に検索し、関連するクラムのテキストを再生成する必要があることを意味します。
今、訪問する/post/abc
と、次のようなパンくずが表示されます
post > abc
ただし、UUIDを含む投稿のタイトルがMy First Post
、の場合、ブレッドクラムを次のように変更します
post > My First Post
async
関数を使用してそれがどのように発生するかを詳しく見ていきましょう。
asPath
vspathname
コード内のルーターインスタンスには、コンポーネントnext/router
に役立つ2つのプロパティがあります。および。ルーターは、ブラウザのURLバーに直接表示されるURLパスです。はURLのより内部的なバージョンであり、パスの動的な部分がコンポーネントに置き換えられています。NextBreadcrumbsasPathpathnameasPathpathname[parameter]
たとえば、/post/abc
上からのパスについて考えてみます。
URLが表示されているとおりにasPath
なります/post/abc
私たちのディレクトリが指示するようpathname
になります/post/[post_id]pages
これらの2つのURLパスバリアントを使用して、ブレッドクラムに関する情報を動的にフェッチする方法を構築できるため、よりコンテキストに適した情報をユーザーに表示できます。
以下で多くのことが行われているので、必要に応じて何度か読み直してください。
const _defaultGetTextGenerator = (param, query) => null;
const _defaultGetDefaultTextGenerator = path => path;
// Pulled out the path part breakdown because its
// going to be used by both `asPath` and `pathname`
const generatePathParts = pathStr => {
const pathWithoutQuery = pathStr.split("?")[0];
return pathWithoutQuery.split("/")
.filter(v => v.length > 0);
}
export default function NextBreadcrumbs({
getTextGenerator=_defaultGetTextGenerator,
getDefaultTextGenerator=_defaultGetDefaultTextGenerator
}) {
const router = useRouter();
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathNestedRoutes = generatePathParts(router.asPath);
const pathnameNestedRoutes = generatePathParts(router.pathname);
const crumblist = asPathParts.map((subpath, idx) => {
// Pull out and convert "[post_id]" into "post_id"
const param = pathnameNestedRoutes[idx].replace("[", "").replace("]", "");
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return {
href, textGenerator: getTextGenerator(param, router.query),
text: getDefaultTextGenerator(subpath, href)
};
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, router.pathname, router.query, getTextGenerator, getDefaultTextGenerator]);
return ( // ...rest below
との両方に同じロジックが使用されているため、asPath
内訳は関数に移動されました。generatePathPartsrouter.asPathrouter.pathname
param
動的ルート値と一致するeterを決定します。これabc
により、結果はになりpost_id
ます。
ネストされたルートparam
eterと関連するすべてのクエリ値(router.query
)は、提供されたものに渡されます。これは、関連するブレッドクラムで使用する動的文字列を返す値または応答のgetTextGenerator
いずれかを返します。nullPromise
useMemo
依存関係配列には、さらに多くの依存関係が追加されています。router.pathname
、、、router.query
およびgetTextGenerator
。
最後に、関連付けられたクラムオブジェクトにこの値が提供されている場合は、Crumb
この値を使用するようにコンポーネントを更新する必要があります。textGenerator
function Crumb({ text: defaultText, textGenerator, href, last=false }) {
const [text, setText] = React.useState(defaultText);
useEffect(async () => {
// If `textGenerator` is nonexistent, then don't do anything
if (!Boolean(textGenerator)) { return; }
// Run the text generator and set the text again
const finalText = await textGenerator();
setText(finalText);
}, [textGenerator]);
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
ブレッドクラムは、静的ルートと動的ルートの両方をクリーンに処理できるようになり、ユーザーフレンドリーな値を表示できるようになりました。上記のコードはコンポーネントのビジネスロジックですが、これはすべて、以下の最後の例のような親コンポーネントで使用できます。
// NextBreadcrumbs.js
const _defaultGetTextGenerator = (param, query) => null;
const _defaultGetDefaultTextGenerator = path => path;
// Pulled out the path part breakdown because its
// going to be used by both `asPath` and `pathname`
const generatePathParts = pathStr => {
const pathWithoutQuery = pathStr.split("?")[0];
return pathWithoutQuery.split("/")
.filter(v => v.length > 0);
}
export default function NextBreadcrumbs({
getTextGenerator=_defaultGetTextGenerator,
getDefaultTextGenerator=_defaultGetDefaultTextGenerator
}) {
const router = useRouter();
const breadcrumbs = React.useMemo(function generateBreadcrumbs() {
const asPathNestedRoutes = generatePathParts(router.asPath);
const pathnameNestedRoutes = generatePathParts(router.pathname);
const crumblist = asPathParts.map((subpath, idx) => {
// Pull out and convert "[post_id]" into "post_id"
const param = pathnameNestedRoutes[idx].replace("[", "").replace("]", "");
const href = "/" + asPathNestedRoutes.slice(0, idx + 1).join("/");
return {
href, textGenerator: getTextGenerator(param, router.query),
text: getDefaultTextGenerator(subpath, href)
};
})
return [{ href: "/", text: "Home" }, ...crumblist];
}, [router.asPath, router.pathname, router.query, getTextGenerator, getDefaultTextGenerator]);
return (
<Breadcrumbs aria-label="breadcrumb">
{breadcrumbs.map((crumb, idx) => (
<Crumb {...crumb} key={idx} last={idx === breadcrumbs.length - 1} />
))}
</Breadcrumbs>
);
}
function Crumb({ text: defaultText, textGenerator, href, last=false }) {
const [text, setText] = React.useState(defaultText);
useEffect(async () => {
// If `textGenerator` is nonexistent, then don't do anything
if (!Boolean(textGenerator)) { return; }
// Run the text generator and set the text again
const finalText = await textGenerator();
setText(finalText);
}, [textGenerator]);
if (last) {
return <Typography color="text.primary">{text}</Typography>
}
return (
<Link underline="hover" color="inherit" href={href}>
{text}
</Link>
);
}
次に、これNextBreadcrumbs
が使用されている例を以下に示します。これは、各ヘルパー関数への参照を1つだけ作成するために使用されることに注意してくださいuseCallback
。これにより、ページレイアウトコンポーネントが再レンダリングされた場合に、ブレッドクラムが不要に再レンダリングされるのを防ぐことができます。これをファイルの最上位スコープに移動することもできますが、そのようにグローバルスコープを汚染するのは好きではありません。
// MyPage.js (Parent Component)
import React from 'react';
import NextBreadcrumbs from "./NextBreadcrumbs";
function MyPageLayout() {
// Either lookup a nice label for the subpath, or just titleize it
const getDefaultTextGenerator = React.useCallback((subpath) => {
return {
"post": "Posts",
"settings": "User Settings",
}[subpath] || titleize(subpath);
}, [])
// Assuming `fetchAPI` loads data from the API and this will use the
// parameter name to determine how to resolve the text. In the example,
// we fetch the post from the API and return it's `title` property
const getTextGenerator = React.useCallback((param, query) => {
return {
"post_id": () => await fetchAPI(`/posts/${query.post_id}/`).title,
}[param];
}, []);
return () {
<div>
{/* ...Whatever else... */}
<NextBreadcrumbs
getDefaultTextGenerator={getDefaultTextGenerator}
getTextGenerator={getTextGenerator}
/>
{/* ...Whatever else... */}
</div>
}
}
これは私のより詳細で技術的な投稿の1つです。楽しんでいただければ幸いです。一貫性と正確性を確保できるよう、コメントまたは連絡してください。うまくいけば、この投稿がNextjsに関するいくつかの戦略や概念を教えてくれました。
ソース:https ://hackernoon.com/implement-a-dynamic-breadcrumb-in-reactnextjs
1626611700
This in the second video in my NextJS framework crash course series! NextJS is a javascript framework that lets you build server-side rendering and static web applications using React. In this video, I talk about what NextJS is, what companies use it, and some of the features that make it great. Then, we use the create-next-app command to create the NextJS boiler plate starter project. We then look at what that generated and go over all the files. In the next video we will start writing code!
NextJS Crash Course Video Outline:
Playlist: https://www.youtube.com/playlist?list=PLL1pJgYmqo2vYtT0v_7axfIG86fyL1whf
Course Intro - https://youtu.be/_dqkETqCJXQ
What is Next.js? - https://youtu.be/L8RaJZodkv8 ⬅️⬅️⬅️ You are here
Pages, CSS, Static Files - https://youtu.be/HM5kB2x1ccw
getInitialProps - https://youtu.be/RgQxcw2R1q0
getStaticProps - https://youtu.be/VH_3hzpAPbQ
getStaticPaths - https://youtu.be/nKg0132Nu0o
getServerSideProps - https://youtu.be/qUhYZi-KMPQ
YouTube API - https://youtu.be/jVc8qVq0NR8
GitHub API - https://youtu.be/4g3Ziy20quY
Strava API - https://youtu.be/fNOUHccIchU
Deploying On Vercel - https://youtu.be/ben3vRAqvKE
Social media dashboard GitHub: https://github.com/bjcarlson42/nextjs-social-dashboard
NextJS website: https://nextjs.org/
My website api route example: https://benjamincarlson.io/api/gear
(0:00) Introduction
(0:43) NextJS Website
(1:00) Why NextJS?
(1:44) Showcase
(2:37) create-next-app command
(5:09) Viewing code in VSCode
(5:57) Pages directory
(7:49) pages/api
(8:37) Viewing the browsable api
(8:59) My personal website api example
(10:11) public folder / gitignore package.json / README.md / yarn.lock
(11:37) Conclusion
#nextjs
#nextjs #nextjs crash course