¿Cómo hacer una página No encontrada con rutas anidadas dinámicas complejas en React Router 6?
Por ejemplo, tengo rutas dinámicas para categorías y páginas de productos. Se parece a esto:
site.com/jeans site.com/jeans/qazXzx123122
Para representar los datos en las páginas de categorías y productos, utilizo el mismo enfoque:
CategoríaPágina
const { products } = useSelector((state: RootState) => state.product); const { categories } = useSelector((state: RootState) => state.category); const { url } = useParams(); const categoryProducts = products.filter((product) => product.category.url === url); const category = categories.find((category) => category.url === url) as Category;
Si voy a la URL incorrecta, por ejemplo, a site.com/jeans111
, la aplicación falla porque no hay una categoría con esa URL y category === undefined
. Intenté resolver el problema con useEffect hook y redirect pero no tuve éxito.
Enfoque que no funciona
useEffect(() => { if (!category.name) { return navigate('/', { replace: true, }); } }, [category, navigate]);
Rutas
const routes = useRoutes([ { path: PATHS.showcase, element: <ShowcasePage />, children: [ { path: '/', element: isDataLoaded ? <DiscountProductsPage /> : <Loader />, }, { path: ':url', children: [ { index: true, element: isDataLoaded ? <CategoryPage /> : <Loader />, }, { path: ':id', element: isDataLoaded ? <ProductPage /> : <Loader />, }, { path: '*', element: <NotFound /> } ], }, { path: PATHS.wishlist, element: isDataLoaded ? <WishlistPage /> : <Loader /> }, { path: PATHS.cart, element: isDataLoaded ? <CartPage /> : <Loader />, }, { path: `${PATHS.cart}/${PATHS.success}`, element: <CheckoutSuccessPage />, }, ], }, { path: PATHS.admin, element: <AdminPage />, children: [ { path: PATHS.orders, element: <OrdersPage />, }, { path: PATHS.products, element: <ProductsPage />, }, { path: PATHS.settings, element: <SettingsPage />, }, ], }, ]);
Creo que su enfoque es correcto, pero desea desviarse de la ruta cuando no hay una category
para la que representar el contenido.
Ejemplo:
const navigate = useNavigate(); const { url } = useParams(); ... const category = categories.find((category) => category.url === url) as Category; useEffect(() => { if (!category) { navigate('/', { replace: true }); } }, [category, navigate]);
Aunque puede ser mejor mostrar una pantalla alternativa en lugar de simplemente sacar al usuario de la ruta.
const navigate = useNavigate(); const { url } = useParams(); ... const category = categories.find((category) => category.url === url) as Category; ... return category ? ( ...JSX... ) : ( <div>No match found.</div> );