stuck-chocolate
stuck-chocolate•5mo ago

how to set custom url for antd useForm hook

const { id } = useParsed(); const { formProps, saveButtonProps, queryResult } = useForm(); I have this setup in my edit screen, and I want to specifically call api/user/getUser for the fetch, and i want to also set api/user/updateUser as the update url. How can i customize those?
94 Replies
kapa.ai
kapa.ai•5mo ago
Hi @biohazard#1521. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To customize the fetch and update URLs in the useForm hook of Refine, you can use the useCustomMutation hook. This hook allows you to specify a custom URL for the mutation. Here is an example of how you can do it:
const { formProps, saveButtonProps, onFinish } = useForm({
resource: "/users/me",
id: "", // I am not sure this will work, please let me know if it does not
});

const { mutate } = useCustomMutation();

const handleOnFinish = (values) => {
mutate({
url: `${API_URL}/users/me/profile`,
method: "patch",
values
});
};

return (
<Edit saveButtonProps={saveButtonProps}>
<Form {...formProps} onFinish={handleOnFinish} layout="vertical">
<Form.Item label="Name" name="name">
<Input />
</Form.Item>
<Form.Item label="Surname" name="surname">
<Input />
</Form.Item>
</Form>
</Edit>
);
const { formProps, saveButtonProps, onFinish } = useForm({
resource: "/users/me",
id: "", // I am not sure this will work, please let me know if it does not
});

const { mutate } = useCustomMutation();

const handleOnFinish = (values) => {
mutate({
url: `${API_URL}/users/me/profile`,
method: "patch",
values
});
};

return (
<Edit saveButtonProps={saveButtonProps}>
<Form {...formProps} onFinish={handleOnFinish} layout="vertical">
<Form.Item label="Name" name="name">
<Input />
</Form.Item>
<Form.Item label="Surname" name="surname">
<Input />
</Form.Item>
</Form>
</Edit>
);
In this example, the useForm hook is used to manage the form state. The useCustomMutation hook is used to specify a custom URL for the mutation. The handleOnFinish function is called when the form is submitted, and it uses the mutate function from useCustomMutation to send a PATCH request to the specified URL with the form values. Please note that this is a general example and you might need to adjust it according to your specific needs. For instance, you might need to adjust the resource and id properties in the useForm hook, and the url and method properties in the mutate function. For more information, you can refer to the Refine documentation (https://refine.dev/docs/api-reference/antd/hooks/form/useForm/#how-can-i-change-the-form-data-before-submitting-it-to-the-api) and the discussion on GitHub (https://github.com/refinedev/refine/discussions/4927). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai•5mo ago
<@680514070167683118> kapa.ai is still learning and improving, please let us know how it did by reacting below
stuck-chocolate
stuck-chocolate•5mo ago
@kapa.ai if i pass the resource as per your example in the useForm hook, it stops making any requests at all when i initially load the form page
kapa.ai
kapa.ai•5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I see, it seems like the useForm hook is not able to infer the correct API endpoint from the resource prop in your case. In Refine, the useForm hook automatically makes a GET request to fetch the data when the component is mounted. This is based on the resource and id props passed to the hook. If these props are not correctly set, the hook might not be able to make the correct request. One possible solution could be to manually fetch the data when the component is mounted using the useQuery hook, and then use the useForm hook only for the submission of the form. Here is an example:
const { data, isLoading } = useQuery({
url: `${API_URL}/users/me`,
});

const { formProps, saveButtonProps } = useForm({
defaultValues: data,
onSubmit: (values) => {
mutate({
url: `${API_URL}/users/me/profile`,
method: "patch",
values,
});
},
});

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

return (
<Edit saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
<Form.Item label="Name" name="name">
<Input />
</Form.Item>
<Form.Item label="Surname" name="surname">
<Input />
</Form.Item>
</Form>
</Edit>
);
const { data, isLoading } = useQuery({
url: `${API_URL}/users/me`,
});

const { formProps, saveButtonProps } = useForm({
defaultValues: data,
onSubmit: (values) => {
mutate({
url: `${API_URL}/users/me/profile`,
method: "patch",
values,
});
},
});

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

return (
<Edit saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
<Form.Item label="Name" name="name">
<Input />
</Form.Item>
<Form.Item label="Surname" name="surname">
<Input />
</Form.Item>
</Form>
</Edit>
);
In this example, the useQuery hook is used to fetch the data when the component is mounted. The useForm hook is then used to manage the form state and handle the form submission. The defaultValues prop of the useForm hook is set to the data fetched by the useQuery hook. Please note that this is a general example and you might need to adjust it according to your specific needs. For instance, you might need to adjust the url property in the useQuery hook and the url and method properties in the mutate function. For more information, you can refer to the Refine documentation (https://refine.dev/docs/api-reference/antd/hooks/form/useForm/#how-can-i-change-the-form-data-before-submitting-it-to-the-api) and the discussion on GitHub (https://github.com/refinedev/refine/discussions/4927). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai•5mo ago
<@680514070167683118> kapa.ai is still learning and improving, please let us know how it did by reacting below
stuck-chocolate
stuck-chocolate•5mo ago
ok now another question, i try to use <ShowButton/> in my list component, and when i try clicking it, it just pushes me to the same list url, which is "/users". What is wrong there? My show and edit buttons: <Table.Column dataIndex="" title="Actions" render={(_, record) => { return ( <> <ShowButton resource="users" size="small" recordItemId={record.id} hideText /> <EditButton resource="users" size="small" recordItemId={record.id} hideText /> </> ); }} @kapa.ai
kapa.ai
kapa.ai•5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The <ShowButton/> and <EditButton/> components in Refine use the resource and recordItemId props to construct the URL to which they will redirect when clicked. The resource prop should match the name of the resource as defined in your <Resource/> component, and the recordItemId prop should be the id of the record you want to show or edit. In your case, you're setting the resource prop to "users" and recordItemId to record.id, which should be correct assuming that your resource is named "users" and your records have a property id which is unique for each record. If clicking the buttons redirects you to the list URL ("/users"), it could mean that the recordItemId is not being correctly set. Make sure that record.id is defined and unique for each record. If you're still having issues, it could be due to a bug or a misconfiguration in your code. In that case, I would recommend checking the Refine documentation (https://refine.dev/docs/ui-integrations/ant-design/components/buttons/show-button#resource) and the Refine GitHub issues (https://github.com/refinedev/refine/issues/1125) for similar problems, or opening a new issue with a detailed description of your problem. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai•5mo ago
<@680514070167683118> kapa.ai is still learning and improving, please let us know how it did by reacting below
stuck-chocolate
stuck-chocolate•5mo ago
it is defined for sure, but it doesn't work. this is my resources definition on the <Refine/> component: resources={[ { name: 'users', list: '/users', create: '/users/create', edit: '/users/edit/:id', show: '/users/show/:id', }, ]} and my routes definitions: <Route path="/users"> <Route index element={<UserList />} /> <Route path="create" element={<UserCreate />} /> <Route path="edit/:id" element={<UserEdit />} /> <Route path="show/:id" element={<UserShow />} /> </Route> @kapa.ai
kapa.ai
kapa.ai•5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Based on your resource and route definitions, everything seems to be set up correctly. The ShowButton and EditButton should redirect to the correct paths when clicked. However, if they're not working as expected, it could be due to a bug or a misconfiguration somewhere else in your code. Here are a few things you could check: 1. Make sure that the record.id is correctly set and unique for each record. You can check this by logging the record.id in the render function of your Table.Column. 2. Make sure that the UserShow and UserEdit components are correctly set up to receive and handle the id parameter from the route. You can check this by logging the id in these components. 3. Make sure that the resource prop in the ShowButton and EditButton matches the name prop in your resource definition. In your case, it should be "users". 4. Make sure that your Route components are correctly nested within a Routes component, and that your Routes component is correctly nested within a BrowserRouter or HashRouter component. If you're still having issues, I would recommend checking the Refine documentation (https://refine.dev/docs/ui-integrations/ant-design/components/buttons/show-button#resource) and the Refine GitHub issues (https://github.com/refinedev/refine/issues/1125) for similar problems, or opening a new issue with a detailed description of your problem. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai•5mo ago
<@680514070167683118> kapa.ai is still learning and improving, please let us know how it did by reacting below
stuck-chocolate
stuck-chocolate•5mo ago
@kapa.ai I have a custom data provider, and i try to use the useForm hook with a custom resource that is not defined anywhere. I want to intercept the request in my data provider and edit the request, but when i add the resource value, no request seems to be happening at all
kapa.ai
kapa.ai•5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- In Refine, the useForm hook automatically makes a GET request to fetch the data when the component is mounted. This is based on the resource and id props passed to the hook. If these props are not correctly set, the hook might not be able to make the correct request. If you're using a custom data provider and you want to intercept the request, you should handle this in your data provider's methods. The resource prop passed to the useForm hook will be passed to your data provider's methods as a parameter. Here's an example of how you can handle this in your data provider:
const dataProvider = {
// other methods...

getOne: (resource, params) => {
if (resource === 'custom-resource') {
// handle the request for 'custom-resource'
} else {
// handle the request for other resources
}
},

// other methods...
};
const dataProvider = {
// other methods...

getOne: (resource, params) => {
if (resource === 'custom-resource') {
// handle the request for 'custom-resource'
} else {
// handle the request for other resources
}
},

// other methods...
};
In this example, the getOne method checks if the resource is 'custom-resource'. If it is, it handles the request in a specific way. If it's not, it handles the request in a different way. If no request is being made when you add the resource value, it could be because your data provider's methods are not correctly handling the resource. Make sure that your data provider's methods are correctly checking the resource and making the appropriate request. For more information, you can refer to the Refine documentation on creating a data provider (https://refine.dev/docs/data/data-provider/#creating-a-data-provider) and the Refine documentation on the useForm hook (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-form#resource). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
stuck-chocolate
stuck-chocolate•5mo ago
the problem is that even if i define it like this:
const { formProps, saveButtonProps, queryResult } = useForm({
resource: 'admingetuser',
id
});
const { formProps, saveButtonProps, queryResult } = useForm({
resource: 'admingetuser',
id
});
the getOne method is never even being called, but if i remove the custom resource, then it does call the default resource name. @kapa.ai
kapa.ai
kapa.ai•5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The useForm hook in Refine uses the resource and id props to construct the API endpoint for the GET request it makes when the component is mounted. If the resource prop is not correctly set, the hook might not be able to make the correct request. If the getOne method is not being called when you set a custom resource, it could be because Refine is not able to match the resource with any of the resources defined in your <Refine> component. In Refine, resources are defined in the <Refine> component and are used to construct the API endpoints for the data provider methods. If you're using a custom resource that is not defined in your <Refine> component, Refine might not be able to construct the correct API endpoint, and therefore might not call the getOne method. If you want to use a custom resource with the useForm hook, you should define this resource in your <Refine> component. Here's an example:
<Refine dataProvider={dataProvider} resources={[{ name: 'admingetuser' }]}>
{/* your routes and components */}
</Refine>
<Refine dataProvider={dataProvider} resources={[{ name: 'admingetuser' }]}>
{/* your routes and components */}
</Refine>
In this example, the admingetuser resource is defined in the <Refine> component. You can then use this resource with the useForm hook:
const { formProps, saveButtonProps, queryResult } = useForm({
resource: 'admingetuser',
id
});
const { formProps, saveButtonProps, queryResult } = useForm({
resource: 'admingetuser',
id
});
Now, when you use the useForm hook with the admingetuser resource, Refine should be able to construct the correct API endpoint and call the getOne method. For more information, you can refer to the Refine documentation on the useForm hook (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-form#resource) and the Refine documentation on resources (https://refine.dev/docs/concepts/resources). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------