show() - edit() route customization

Hi, Is it possible to customize how the show and edit commands work? I need to use two different routes for the same resource based on a custom logic e.g. Case 1 : /resource/[id] Case 2: /custom/resource/[id] is it possible to customize show so that, according to the specific logic, I navigate to a different page?
8 Replies
kapa.ai
kapa.ai3w ago
Hi @simoneb. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Yes, it is possible to customize how the show and edit commands work in refine, allowing you to use different routes for the same resource based on custom logic. This can be achieved by customizing the resource definitions and using the useNavigation hook. Here's how you can approach this: 1. Custom Resource Definition: You can define custom paths for your resource actions in the resources prop of the <Refine> component. This allows you to specify different routes for the same resource. Refine v4 Announcement shows an example of how you can define custom paths:
resources={[
{
name: "products",
list: "/:tenantId/products",
show: "/:tenantId/products/:id",
edit: "/:tenantId/products/:id/edit",
create: "/:tenantId/products/create",
}
]}

resources={[
{
name: "products",
list: "/:tenantId/products",
show: "/:tenantId/products/:id",
edit: "/:tenantId/products/:id/edit",
create: "/:tenantId/products/create",
}
]}

You can adapt this to your specific needs, for example:
resources={[
{
name: "resource",
show: "/resource/:id",
edit: "/resource/:id/edit",
},
{
name: "customResource",
show: "/custom/resource/:id",
edit: "/custom/resource/:id/edit",
}
]}

resources={[
{
name: "resource",
show: "/resource/:id",
edit: "/resource/:id/edit",
},
{
name: "customResource",
show: "/custom/resource/:id",
edit: "/custom/resource/:id/edit",
}
]}

2. Using useNavigation Hook: To implement your custom logic for navigation, you can use the useNavigation hook. This hook provides methods like show and edit that you can use to navigate to the appropriate route based on your logic. useNavigation API Reference provides details on how to use this hook:
import { useNavigation } from "@refinedev/core";

const { show, edit } = useNavigation();
// Your custom logic to determine which route to use
const customNavigate = (id) => {
if (someCondition) {
show("resource", id);
} else {
show("customResource", id);
}
};

import { useNavigation } from "@refinedev/core";

const { show, edit } = useNavigation();
// Your custom logic to determine which route to use
const customNavigate = (id) => {
if (someCondition) {
show("resource", id);
} else {
show("customResource", id);
}
};

You can apply similar logic for the edit function as well. 3. Implementing in Components: You can use this custom navigation in your components, such as in a custom <ShowButton> or <EditButton>:
const CustomShowButton = ({ id }) => {
const { show } = useNavigation();

const handleClick = () => {
if (someCondition) {
show("resource", id);
} else {
show("customResource", id);
}
};

return <button onClick={handleClick}>Show</button>;
};

const CustomShowButton = ({ id }) => {
const { show } = useNavigation();

const handleClick = () => {
if (someCondition) {
show("resource", id);
} else {
show("customResource", id);
}
};

return <button onClick={handleClick}>Show</button>;
};

By combining these approaches, you can create a flexible system that navigates to different routes based on your specific logic, while still leveraging refine's powerful routing capabilities. Remember to handle these custom routes in your router configuration as well, to ensure they are properly rendered. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@539513465103056900> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
generous-apricot
generous-apricotOP3w ago
ok, I need to use useNavigation BUT ... is it possible to add the logic site-wide, instead of adding the customNavigate per-page ? @kapa.ai
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, it's possible to implement your custom navigation logic site-wide in refine, rather than adding it to each page individually. You can achieve this by creating a custom hook that wraps the useNavigation hook and applies your logic. Here's how you can do it: 1. Create a custom navigation hook: You can create a new hook, let's call it useCustomNavigation, that encapsulates your navigation logic:
import { useNavigation } from "@refinedev/core";

const useCustomNavigation = () => {
const navigation = useNavigation();

const customShow = (resource: string, id: string | number) => {
if (someCondition) {
navigation.show("resource", id);
} else {
navigation.show("customResource", id);
}
};

const customEdit = (resource: string, id: string | number) => {
if (someCondition) {
navigation.edit("resource", id);
} else {
navigation.edit("customResource", id);
}
};

return {
...navigation,
show: customShow,
edit: customEdit,
};
};

export default useCustomNavigation;
import { useNavigation } from "@refinedev/core";

const useCustomNavigation = () => {
const navigation = useNavigation();

const customShow = (resource: string, id: string | number) => {
if (someCondition) {
navigation.show("resource", id);
} else {
navigation.show("customResource", id);
}
};

const customEdit = (resource: string, id: string | number) => {
if (someCondition) {
navigation.edit("resource", id);
} else {
navigation.edit("customResource", id);
}
};

return {
...navigation,
show: customShow,
edit: customEdit,
};
};

export default useCustomNavigation;
2. Use the custom hook throughout your application: Instead of using useNavigation directly in your components, you can now use your useCustomNavigation hook:
import useCustomNavigation from "./useCustomNavigation";

const MyComponent = () => {
const { show, edit } = useCustomNavigation();

// Now you can use show and edit, and they will automatically
// apply your custom logic
return (
<>
<button onClick={() => show("resource", "1")}>Show</button>
<button onClick={() => edit("resource", "1")}>Edit</button>
</>
);
};
import useCustomNavigation from "./useCustomNavigation";

const MyComponent = () => {
const { show, edit } = useCustomNavigation();

// Now you can use show and edit, and they will automatically
// apply your custom logic
return (
<>
<button onClick={() => show("resource", "1")}>Show</button>
<button onClick={() => edit("resource", "1")}>Edit</button>
</>
);
};
This approach allows you to implement your custom navigation logic in one place and use it consistently throughout your application. It's a more maintainable solution as you only need to update the logic in one place if you need to make changes in the future. Remember to adjust the someCondition in the custom hook to match your specific logic for determining which route to use. For more information on creating custom hooks in refine, you can refer to the Hook Concept documentation, which explains how refine adopts a hook-based architecture for enhanced development experience and application performance. useNavigation API Reference provides details on the original useNavigation hook that you're extending with your custom logic. This approach aligns with refine's philosophy of providing unified, headless hooks that can be customized to fit your specific needs while maintaining consistency across your application. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@539513465103056900> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
generous-apricot
generous-apricotOP3w ago
ok, it actually makes sense, thanks is it possible to get, from show() function, the route/path that will be used? @kapa.ai
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, it is possible to get the route/path that will be used by the show() function in refine. You can achieve this by using the showUrl method provided by the useNavigation hook. Here's how you can do it:
import { useNavigation } from "@refinedev/core";

const MyComponent = () => {
const { showUrl } = useNavigation();

// Get the URL for the show page of a resource with id "1"
const url = showUrl("posts", "1");

console.log(url); // This will log the URL that would be used by show()

return (
// Your component JSX
);
};
import { useNavigation } from "@refinedev/core";

const MyComponent = () => {
const { showUrl } = useNavigation();

// Get the URL for the show page of a resource with id "1"
const url = showUrl("posts", "1");

console.log(url); // This will log the URL that would be used by show()

return (
// Your component JSX
);
};
The showUrl method returns the show page URL of the given resource and id, without actually navigating to it. This allows you to inspect or use the URL as needed. useNavigation API Reference provides more details on the showUrl method:
showUrl: (resource: string, id: BaseKey, meta?: Record<string, any>) => string
showUrl: (resource: string, id: BaseKey, meta?: Record<string, any>) => string
This method takes the resource name, the record id, and an optional meta object for additional parameters. It returns the URL as a string. For example:
showUrl("posts", "1"); // It returns the `/posts/show/1` URL
showUrl("posts", "1"); // It returns the `/posts/show/1` URL
You can use this method to get the URL that would be used by the show() function, allowing you to inspect or manipulate it before actual navigation occurs. Remember that the actual URL structure depends on how you've defined your resource routes in your refine configuration. If you've customized the routes, the showUrl method will respect those customizations. Refine Component Documentation mentions that you can customize the show path of a resource, which will be reflected in the URL returned by showUrl:
resources={[
{
name: "posts",
show: "/posts/:id/details",
}
]}
resources={[
{
name: "posts",
show: "/posts/:id/details",
}
]}
In this case, showUrl("posts", "1") would return /posts/1/details. This feature allows you to programmatically determine the URL that will be used for navigation, which can be useful for creating custom navigation logic or for debugging purposes. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@539513465103056900> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?