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.
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:
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:
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:
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.
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> ); };