Skip to main content

Redirects

Now we've updated our components to benefit from the parameter inference of Refine. In this step, we'll be learning about the redirects and how to benefit from them in our forms and auth provider.

Refine can manage redirects automatically for you. After a successful form submission, Refine will try to redirect the user to the appropriate page.

Just like the forms, redirects are also supported in the auth provider. By providing a redirectTo parameter to the return values of the login, logout and onError method, you can redirect the user to the appropriate page. Such as the index page after a successful login or the login page after a successful logout.

Redirecting After Form Submission

By default, Refine will redirect the user to the list page of the target resource after a successful form submission. We can customize this behavior by providing a redirect parameter to the useForm hook.

TIP

You can also use the options.redirect prop of the <Refine /> component to set a default redirect for all forms per action.

Showing the Record After Update

Let's update our <EditProduct /> component and provide a redirect parameter to let users redirect to the show page of the edited product after a successful form submission.

Update your src/pages/products/edit.tsx file by adding the following lines:

src/pages/products/edit.tsx
import { useForm, useSelect } from "@refinedev/core";

export const EditProduct = () => {
const { onFinish, mutation, query } = useForm({
// This will redirect to the show page after the mutation is successful.
// Default value is `"list"`.
// We can also provide `false` to disable the redirect.
redirect: "show",
});

/* ... */
};

Continue to Edit the Record After Creation

Let's update our <CreateProduct /> component and provide a redirect parameter to let users continue to edit the created product after a successful form submission.

Update your src/pages/products/create.tsx file by adding the following lines:

src/pages/products/create.tsx
import { useForm, useSelect } from "@refinedev/core";

export const CreateProduct = () => {
const { onFinish, mutation } = useForm({
// We can also provide `false` to disable the redirect.
// Default value is `"list"`.
redirect: "edit",
});

/* ... */
};

Handling Redirects in Auth Provider

Refine provides a simple way to integrate routing into your auth provider. By providing a redirectTo parameter to the return values of the login, logout and onError methods, you can redirect the user to the appropriate page. Such as the index page after a successful login or the login page after a successful logout.

Let's update our src/providers/auth-provider.ts file and provide a redirectTo properties to the return values of the login and logout methods. We want to redirect the user to the index page after a successful login and to the login page after a successful logout.

Update your src/providers/auth-provider.ts file by adding the following lines:

src/providers/auth-provider.ts
import { AuthProvider } from "@refinedev/core";

export const authProvider: AuthProvider = {
logout: async () => {
localStorage.removeItem("my_access_token");

// Let's redirect to the login page after a successful logout.
return { success: true, redirectTo: "/login" };
},
login: async ({ email, password }) => {
const response = await fetch(
"https://api.fake-rest.refine.dev/auth/login",
{
method: "POST",
body: JSON.stringify({ email, password }),
headers: {
"Content-Type": "application/json",
},
},
);

const data = await response.json();

if (data.token) {
localStorage.setItem("my_access_token", data.token);
// Let's redirect to the index page after a successful login.
return { success: true, redirectTo: "/" };
}

return { success: false };
},
/* ... */
};

Now we've learned about the redirects and how to benefit from them in our forms and auth provider, let's move on to the next step. In the next step, we'll be learning about how to store the current table state in the URL.

Was this helpful?
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({
    pagination: { current: 1, pageSize: 10 },
    sorters: { initial: [{ field: "id", order: "asc" }] },
  });

  const { showUrl, editUrl } = useNavigation();

  const { data: categories } = useMany({
    resource: "categories",
    ids: data?.data?.map((product) => product.category?.id) ?? [],
  });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  const onPrevious = () => {
    if (current > 1) {
      setCurrent(current - 1);
    }
  };

  const onNext = () => {
    if (current < pageCount) {
      setCurrent(current + 1);
    }
  };

  const onPage = (page: number) => {
    setCurrent(page);
  };

  const getSorter = (field: string) => {
    const sorter = sorters?.find((sorter) => sorter.field === field);

    if (sorter) {
      return sorter.order;
    }
  };

  const onSort = (field: string) => {
    const sorter = getSorter(field);
    setSorters(
      sorter === "desc"
        ? []
        : [
            {
              field,
              order: sorter === "asc" ? "desc" : "asc",
            },
          ],
    );
  };

  const indicator = { asc: "⬆️", desc: "⬇️" };

  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">
        <button type="button" onClick={onPrevious}>
          {"<"}
        </button>
        <div>
          {current - 1 > 0 && (
            <span onClick={() => onPage(current - 1)}>{current - 1}</span>
          )}
          <span className="current">{current}</span>
          {current + 1 < pageCount && (
            <span onClick={() => onPage(current + 1)}>{current + 1}</span>
          )}
        </div>
        <button type="button" onClick={onNext}>
          {">"}
        </button>
      </div>
    </div>
  );
};
installing dependencies
installing dependencies