Skip to main content

Navigation

Now we've set up our routes and resources. In this step, we'll be learning about Refine's navigation helpers and how to use them in our app.

TIP

You can always use the preferred methods of your routing library to navigate between pages. Refine's navigation hooks are helpers to make it easier to navigate between any action of any resource.

We'll use the useNavigation hook and create buttons to navigate to the create, edit and show pages of the products. Additionally we'll provide a link to the list page of the products in the <Header /> component.

We'll be using the useNavigation hook from @refinedev/core and the <Link /> component of the react-router-dom library to create links to the list page and the create page of the products.

Let's update our <Header /> component and add a link to the list page of the products:

src/components/header.tsx
import React from "react";
import { useLogout, useGetIdentity, useNavigation } from "@refinedev/core";

import { Link } from "react-router-dom";

export const Header = () => {
const { mutate, isLoading } = useLogout();
const { data: identity } = useGetIdentity();

// You can also use methods like list or create to trigger navigation.
// We're using url methods to provide more semantically correct html.
const { listUrl, createUrl } = useNavigation();

return (
<>
<h2>
<span>Welcome, </span>
<span>{identity?.name ?? ""}</span>
</h2>
<Link to={listUrl("protected-products")}>List Products</Link>
<Link to={createUrl("protected-products")}>Create Product</Link>
<button type="button" disabled={isLoading} onClick={mutate}>
Logout
</button>
</>
);
};

Adding Show and Edit Buttons to the List Page

Similarly, we'll update the <ListProducts /> component and add links for showing and editing the products.

src/pages/products/list.tsx
import { useTable, useMany, useNavigation } from "@refinedev/core";

import { Link } from "react-router-dom";

export const ListProducts = () => {
const {
tableQuery: { data, isLoading },
current,
setCurrent,
pageCount,
sorters,
setSorters,
} = useTable({
resource: "protected-products",
pagination: { current: 1, pageSize: 10 },
sorters: { initial: [{ field: "id", order: "asc" }] },
});

// You can also use methods like show or list to trigger navigation.
// We're using url methods to provide more semantically correct html.
const { showUrl, editUrl } = useNavigation();

/* ... */

return (
<div>
<h1>Products</h1>
<table>
<thead>
<tr>
<th onClick={() => onSort("id")}>
ID {indicator[getSorter("id")]}
</th>
<th onClick={() => onSort("name")}>
Name {indicator[getSorter("name")]}
</th>
<th>Category</th>
<th onClick={() => onSort("material")}>
Material {indicator[getSorter("material")]}
</th>
<th onClick={() => onSort("price")}>
Price {indicator[getSorter("price")]}
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{data?.data?.map((product) => (
<tr key={product.id}>
<td>{product.id}</td>
<td>{product.name}</td>
<td>
{
categories?.data?.find(
(category) => category.id == product.category?.id,
)?.title
}
</td>
<td>{product.material}</td>
<td>{product.price}</td>
<td>
<Link to={showUrl("protected-products", product.id)}>Show</Link>
<Link to={editUrl("protected-products", product.id)}>Edit</Link>
</td>
</tr>
))}
</tbody>
</table>
<div className="pagination">{/* ... */}</div>
</div>
);
};
INFORMATION

You can also use anchors and any other navigation methods provided by your routing library to move between pages, without being limited to the useNavigation hook.

Now we've learned about the navigating between pages with Refine's useNavigation hook. In the next step, we'll be updating our components to benefit from the parameter inference of Refine.

Was this helpful?
import { Refine, Authenticated } from "@refinedev/core";
import routerProvider, { NavigateToResource } from "@refinedev/react-router-v6";

import { BrowserRouter, Routes, Route, Outlet } from "react-router-dom";

import { dataProvider } from "./providers/data-provider";
import { authProvider } from "./providers/auth-provider";

import { ShowProduct } from "./pages/products/show";
import { EditProduct } from "./pages/products/edit";
import { ListProducts } from "./pages/products/list";
import { CreateProduct } from "./pages/products/create";

import { Login } from "./pages/login";
import { Header } from "./components/header";

export default function App(): JSX.Element {
  return (
    <BrowserRouter>
      <Refine
          dataProvider={dataProvider}
          authProvider={authProvider}
          routerProvider={routerProvider}
          resources={[
            {
                name: "protected-products",
                list: "/products",
                show: "/products/:id",
                edit: "/products/:id/edit",
                create: "/products/create",
                meta: { label: "Products" },
            }
          ]}
      >
        <Routes>
            <Route
                element={(
                    <Authenticated key="authenticated-routes" redirectOnFail="/login">
                        <Header />
                        <Outlet />
                    </Authenticated>
                )}
            >
                <Route
                    index
                    element={<NavigateToResource resource="protected-products" />}
                />
                <Route path="/products">
                    <Route index element={<ListProducts />} />
                    <Route path=":id" element={<ShowProduct />} />
                    <Route path=":id/edit" element={<EditProduct />} />
                    <Route path="create" element={<CreateProduct />} />
                </Route>
            </Route>
            <Route
                element={(
                    <Authenticated key="auth-pages" fallback={<Outlet />}>
                        <NavigateToResource resource="protected-products" />
                    </Authenticated>
                )}
            >
                <Route path="/login" element={<Login />} />
            </Route>
        </Routes>
      </Refine>
    </BrowserRouter>
  );
}
installing dependencies
installing dependencies