I would like to upload an image

export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];
console.log(firstSegment);
const {
saveButtonProps,
refineCore: { formLoading, onFinish },
handleSubmit,
register,
control,
formState: { errors },
} = useForm({
defaultValues: {
project: firstSegment,
},
});

return (
<Create
isLoading={formLoading}
saveButtonProps={saveButtonProps}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column' }}
autoComplete="off"
>
export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];
console.log(firstSegment);
const {
saveButtonProps,
refineCore: { formLoading, onFinish },
handleSubmit,
register,
control,
formState: { errors },
} = useForm({
defaultValues: {
project: firstSegment,
},
});

return (
<Create
isLoading={formLoading}
saveButtonProps={saveButtonProps}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column' }}
autoComplete="off"
>
`
11 Replies
kapa.ai
kapa.ai3w ago
Hi @florent. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To add image upload functionality to your form using refine and React Hook Form, you can use the useForm hook from @refinedev/react-hook-form along with a file input field. Here's how you can modify your code to include image upload:
import { useState } from "react";
import { useForm } from "@refinedev/react-hook-form";
import { Create, useApiUrl } from "@refinedev/core";
import { Box, Typography, TextField } from "@mui/material";
import { LoadingButton } from "@mui/lab";
import FileUploadIcon from "@mui/icons-material/FileUpload";

export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];
const [isUploadLoading, setIsUploadLoading] = useState(false);
const apiUrl = useApiUrl();

const {
saveButtonProps,
refineCore: { formLoading, onFinish },
register,
setValue,
formState: { errors },
} = useForm({
defaultValues: {
project: firstSegment,
},
});

const onChangeHandler = async (event: React.ChangeEvent<HTMLInputElement>) => {
try {
setIsUploadLoading(true);

const formData = new FormData();
const file = event.target.files?.[0];

if (file) {
formData.append("file", file);

// Replace this with your actual upload API endpoint
const res = await fetch(`${apiUrl}/upload`, {
method: "POST",
body: formData,
});

if (res.ok) {
const data = await res.json();
setValue("image", data.url);
}
}
} catch (error) {
// Handle error
} finally {
setIsUploadLoading(false);
}
};
return (
<Create
isLoading={formLoading}
saveButtonProps={saveButtonProps}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column' }}
autoComplete="off"
>
<TextField
{...register("project")}
margin="normal"
fullWidth
InputProps={{
readOnly: true,
}}
label="Project"
/>
<input
type="file"
id="image-input"
hidden
onChange={onChangeHandler}
/>
<input
type="hidden"
{...register("image", {
required: "This field is required",
})}
/>
<LoadingButton
loading={isUploadLoading}
loadingPosition="end"
endIcon={<FileUploadIcon />}
variant="contained"
component="label"
htmlFor="image-input"
sx={{ mt: 2 }}
>
Upload Image
</LoadingButton>
{errors.image && (
<Typography variant="caption" color="error">
{errors.image.message}
</Typography>
)}
{/* Add other form fields here */}
</Box>
</Create>
);
}
import { useState } from "react";
import { useForm } from "@refinedev/react-hook-form";
import { Create, useApiUrl } from "@refinedev/core";
import { Box, Typography, TextField } from "@mui/material";
import { LoadingButton } from "@mui/lab";
import FileUploadIcon from "@mui/icons-material/FileUpload";

export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];
const [isUploadLoading, setIsUploadLoading] = useState(false);
const apiUrl = useApiUrl();

const {
saveButtonProps,
refineCore: { formLoading, onFinish },
register,
setValue,
formState: { errors },
} = useForm({
defaultValues: {
project: firstSegment,
},
});

const onChangeHandler = async (event: React.ChangeEvent<HTMLInputElement>) => {
try {
setIsUploadLoading(true);

const formData = new FormData();
const file = event.target.files?.[0];

if (file) {
formData.append("file", file);

// Replace this with your actual upload API endpoint
const res = await fetch(`${apiUrl}/upload`, {
method: "POST",
body: formData,
});

if (res.ok) {
const data = await res.json();
setValue("image", data.url);
}
}
} catch (error) {
// Handle error
} finally {
setIsUploadLoading(false);
}
};
return (
<Create
isLoading={formLoading}
saveButtonProps={saveButtonProps}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column' }}
autoComplete="off"
>
<TextField
{...register("project")}
margin="normal"
fullWidth
InputProps={{
readOnly: true,
}}
label="Project"
/>
<input
type="file"
id="image-input"
hidden
onChange={onChangeHandler}
/>
<input
type="hidden"
{...register("image", {
required: "This field is required",
})}
/>
<LoadingButton
loading={isUploadLoading}
loadingPosition="end"
endIcon={<FileUploadIcon />}
variant="contained"
component="label"
htmlFor="image-input"
sx={{ mt: 2 }}
>
Upload Image
</LoadingButton>
{errors.image && (
<Typography variant="caption" color="error">
{errors.image.message}
</Typography>
)}
{/* Add other form fields here */}
</Box>
</Create>
);
}
This code adds an image upload functionality to your form. Here's what it does: 1. We import necessary components and hooks from refine and Material-UI. 2. We add a state isUploadLoading to manage the loading state of the upload. 3. We use the useApiUrl hook to get the API URL for file upload. 4. We add a hidden file input and a hidden text input for the image URL. 5. We create an onChangeHandler function that handles the file upload when a file is selected. 6. We add a LoadingButton that triggers the file input when clicked. This implementation is based on the refine documentation for file upload. You may need to adjust the upload endpoint (${apiUrl}/upload) to match your actual API. For more details on file upload with refine, you can refer to the Refine Strapi v4 File Upload documentation. Remember to handle errors appropriately and adjust the code to fit your specific needs and API requirements. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
helpful-purple
helpful-purpleOP3w ago
@kapa.ai But onSubmit not woking
export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];
console.log(firstSegment);
const {
saveButtonProps,
refineCore: { formLoading, onFinish },
handleSubmit,
register,
control,
formState: { errors },
} = useForm({});

const onSubmit = async (formData: any) => {
console.log('Form Data:', formData);
try {
const formDataToSend = new FormData();
formDataToSend.append('productName', formData.productName);
formDataToSend.append('productNo', formData.productNo);

if (formData.thumbnail && formData.thumbnail[0]) {
formDataToSend.append('file', formData.thumbnail[0]);
console.log('Thumbnail file:', formData.thumbnail[0]);
}

const { data } = await dataProvider.default.setProduct({
variables: formDataToSend,
});
console.log('Product created:', data);
} catch (error) {
console.error('Error creating product:', error);
}
};

return (
<Create
isLoading={formLoading}
saveButtonProps={saveButtonProps}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column' }}
autoComplete="off"
onSubmit={handleSubmit(onSubmit)}
>
export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];
console.log(firstSegment);
const {
saveButtonProps,
refineCore: { formLoading, onFinish },
handleSubmit,
register,
control,
formState: { errors },
} = useForm({});

const onSubmit = async (formData: any) => {
console.log('Form Data:', formData);
try {
const formDataToSend = new FormData();
formDataToSend.append('productName', formData.productName);
formDataToSend.append('productNo', formData.productNo);

if (formData.thumbnail && formData.thumbnail[0]) {
formDataToSend.append('file', formData.thumbnail[0]);
console.log('Thumbnail file:', formData.thumbnail[0]);
}

const { data } = await dataProvider.default.setProduct({
variables: formDataToSend,
});
console.log('Product created:', data);
} catch (error) {
console.error('Error creating product:', error);
}
};

return (
<Create
isLoading={formLoading}
saveButtonProps={saveButtonProps}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column' }}
autoComplete="off"
onSubmit={handleSubmit(onSubmit)}
>
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Based on the code you've provided, it seems that the onSubmit function is not being triggered. This is likely because you're not properly connecting the onSubmit function to the form submission process in refine. Let's modify your code to make it work:
import { useForm } from "@refinedev/react-hook-form";
import { Create } from "@refinedev/mui";
import { Box, Typography } from "@mui/material";
import { usePathname } from "next/navigation";

export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];
console.log(firstSegment);

const {
saveButtonProps,
refineCore: { formLoading, onFinish },
register,
handleSubmit,
formState: { errors },
} = useForm();

const onSubmit = async (formData: any) => {
console.log('Form Data:', formData);
try {
const formDataToSend = new FormData();
formDataToSend.append('productName', formData.productName);
formDataToSend.append('productNo', formData.productNo);

if (formData.thumbnail && formData.thumbnail[0]) {
formDataToSend.append('file', formData.thumbnail[0]);
console.log('Thumbnail file:', formData.thumbnail[0]);
}

// Use onFinish instead of dataProvider.default.setProduct
await onFinish(formDataToSend);
console.log('Product created successfully');
} catch (error) {
console.error('Error creating product:', error);
}
};
return (
<Create
isLoading={formLoading}
saveButtonProps={{
...saveButtonProps,
onClick: handleSubmit(onSubmit),
}}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column' }}
autoComplete="off"
>
{/* Your form fields go here */}
<input {...register("productName")} placeholder="Product Name" />
<input {...register("productNo")} placeholder="Product Number" />
<input type="file" {...register("thumbnail")} />
</Box>
</Create>
);
}
import { useForm } from "@refinedev/react-hook-form";
import { Create } from "@refinedev/mui";
import { Box, Typography } from "@mui/material";
import { usePathname } from "next/navigation";

export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];
console.log(firstSegment);

const {
saveButtonProps,
refineCore: { formLoading, onFinish },
register,
handleSubmit,
formState: { errors },
} = useForm();

const onSubmit = async (formData: any) => {
console.log('Form Data:', formData);
try {
const formDataToSend = new FormData();
formDataToSend.append('productName', formData.productName);
formDataToSend.append('productNo', formData.productNo);

if (formData.thumbnail && formData.thumbnail[0]) {
formDataToSend.append('file', formData.thumbnail[0]);
console.log('Thumbnail file:', formData.thumbnail[0]);
}

// Use onFinish instead of dataProvider.default.setProduct
await onFinish(formDataToSend);
console.log('Product created successfully');
} catch (error) {
console.error('Error creating product:', error);
}
};
return (
<Create
isLoading={formLoading}
saveButtonProps={{
...saveButtonProps,
onClick: handleSubmit(onSubmit),
}}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column' }}
autoComplete="off"
>
{/* Your form fields go here */}
<input {...register("productName")} placeholder="Product Name" />
<input {...register("productNo")} placeholder="Product Number" />
<input type="file" {...register("thumbnail")} />
</Box>
</Create>
);
}
Here are the key changes made to make the onSubmit function work: 1. We've removed the onSubmit attribute from the <Box> component. In refine, form submission is typically handled through the saveButtonProps. 2. We've modified the saveButtonProps passed to the <Create> component:
saveButtonProps={{
...saveButtonProps,
onClick: handleSubmit(onSubmit),
}}

saveButtonProps={{
...saveButtonProps,
onClick: handleSubmit(onSubmit),
}}

This connects your onSubmit function to the save button's click event, while preserving other properties of saveButtonProps. 3. Inside the onSubmit function, we've replaced dataProvider.default.setProduct with onFinish. The onFinish function is provided by refine's useForm hook and handles the form submission process, including sending the data to the server. 4. We've added some example form fields using the register function from useForm. Make sure to adjust these fields according to your actual form requirements. These changes should make your onSubmit function work as expected. When the save button is clicked, it will trigger your onSubmit function, which will then use refine's onFinish function to send the data to the server. For more details on form handling in refine, you can refer to the React Hook Form Usage documentation. Remember to handle any errors that might occur during form submission and adjust the code to fit your specific API requirements. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
helpful-purple
helpful-purpleOP3w ago
@kapa.ai But formData is undefined
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize for the confusion. If formData is undefined, it suggests that there might be an issue with how the form data is being collected or passed to the onSubmit function. Let's modify the code to ensure that the form data is properly captured and logged. Here's an updated version that should help identify the issue:
import { useForm } from "@refinedev/react-hook-form";
import { Create } from "@refinedev/mui";
import { Box, Typography, TextField, Button } from "@mui/material";
import { usePathname } from "next/navigation";

export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];

const {
saveButtonProps,
refineCore: { formLoading, onFinish },
register,
handleSubmit,
formState: { errors },
} = useForm();

const onSubmit = async (formData: any) => {
console.log('Form Data in onSubmit:', formData);
if (!formData) {
console.error('Form data is undefined');
return;
}

try {
const formDataToSend = new FormData();
formDataToSend.append('productName', formData.productName || '');
formDataToSend.append('productNo', formData.productNo || '');

if (formData.thumbnail && formData.thumbnail[0]) {
formDataToSend.append('file', formData.thumbnail[0]);
console.log('Thumbnail file:', formData.thumbnail[0]);
}

// Log the FormData contents
for (let [key, value] of formDataToSend.entries()) {
console.log(key, value);
}

await onFinish(formDataToSend);
console.log('Product created successfully');
} catch (error) {
console.error('Error creating product:', error);
}
};
return (
<Create
isLoading={formLoading}
saveButtonProps={saveButtonProps}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}
autoComplete="off"
onSubmit={handleSubmit(onSubmit)}
>
<TextField
{...register("productName", { required: "This field is required" })}
label="Product Name"
error={!!errors.productName}
helperText={errors.productName?.message as string}
/>
<TextField
{...register("productNo", { required: "This field is required" })}
label="Product Number"
error={!!errors.productNo}
helperText={errors.productNo?.message as string}
/>
<input
type="file"
{...register("thumbnail")}
/>
<Button type="submit" variant="contained">Submit</Button>
</Box>
</Create>
);
}
import { useForm } from "@refinedev/react-hook-form";
import { Create } from "@refinedev/mui";
import { Box, Typography, TextField, Button } from "@mui/material";
import { usePathname } from "next/navigation";

export default function NatureClassCreate() {
const currentPath = usePathname();
const firstSegment = currentPath.split('/')[1];

const {
saveButtonProps,
refineCore: { formLoading, onFinish },
register,
handleSubmit,
formState: { errors },
} = useForm();

const onSubmit = async (formData: any) => {
console.log('Form Data in onSubmit:', formData);
if (!formData) {
console.error('Form data is undefined');
return;
}

try {
const formDataToSend = new FormData();
formDataToSend.append('productName', formData.productName || '');
formDataToSend.append('productNo', formData.productNo || '');

if (formData.thumbnail && formData.thumbnail[0]) {
formDataToSend.append('file', formData.thumbnail[0]);
console.log('Thumbnail file:', formData.thumbnail[0]);
}

// Log the FormData contents
for (let [key, value] of formDataToSend.entries()) {
console.log(key, value);
}

await onFinish(formDataToSend);
console.log('Product created successfully');
} catch (error) {
console.error('Error creating product:', error);
}
};
return (
<Create
isLoading={formLoading}
saveButtonProps={saveButtonProps}
title={<Typography variant="h5">상품 추가</Typography>}
>
<Box
component="form"
sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}
autoComplete="off"
onSubmit={handleSubmit(onSubmit)}
>
<TextField
{...register("productName", { required: "This field is required" })}
label="Product Name"
error={!!errors.productName}
helperText={errors.productName?.message as string}
/>
<TextField
{...register("productNo", { required: "This field is required" })}
label="Product Number"
error={!!errors.productNo}
helperText={errors.productNo?.message as string}
/>
<input
type="file"
{...register("thumbnail")}
/>
<Button type="submit" variant="contained">Submit</Button>
</Box>
</Create>
);
}
In this updated version: 1. We've added more detailed logging in the onSubmit function to help identify where the issue might be occurring. 2. We've added a check to see if formData is undefined and log an error if it is. 3. We've moved the form submission logic back to the <Box> component by adding the onSubmit prop:
onSubmit={handleSubmit(onSubmit)}

onSubmit={handleSubmit(onSubmit)}

4. We've added a submit button to the form to ensure there's a way to trigger the submission. 5. We've used Material-UI's TextField components for better form field handling and error display. 6. We've added some basic validation to the form fields. This setup should help identify why formData is undefined. Here are a few things to check: 1. Make sure you're actually filling out the form fields before submitting. 2. Check the browser console for any error messages that might be occurring during form submission. 3. Verify that the register function is being called correctly for each form field. If you're still experiencing issues, it might be helpful to log the entire form state in the onSubmit function:
const onSubmit = async (formData: any) => {
console.log('Entire form state:', formData);
// ... rest of the function
};
const onSubmit = async (formData: any) => {
console.log('Entire form state:', formData);
// ... rest of the function
};
This will give you a complete picture of what data is being captured by the form. For more information on troubleshooting form issues with refine and React Hook Form, you can refer to the React Hook Form Usage documentation. If the problem persists, please provide more details about the specific error you're seeing or any console logs that appear when you try to submit the form. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
helpful-purple
helpful-purpleOP3w ago
@kapa.ai return ( <Edit title={ <Typography variant="h5">{selectedProduct?.product_name}</Typography> } isLoading={formLoading} saveButtonProps={saveButtonProps} footerButtons={() => <></>} > const handleDelete = async (id: number) => { const confirmDelete = window.confirm( ID가 ${id}인 항목을 삭제하시겠습니까?, ); if (!confirmDelete) { return; } console.log(ID가 ${id}인 항목을 삭제합니다.); try { const response = await dataProvider.default.removeDetail({ resource: 'products', id: id as BaseKey, variables: { id: id }, }); console.log('삭제 성공:', response); window.location.reload(); // 삭제 후 페이지 새로고침 } catch (error) { console.error('삭제 중 오류 발생:', error); } }; how to success after Refresh?
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To handle the successful deletion of a product and refresh the data without reloading the entire page, you can use refine's built-in data invalidation mechanism. This approach is more efficient and provides a better user experience than using window.location.reload(). Here's how you can modify your code to achieve this:
import { useInvalidate, useNotification } from "@refinedev/core";
import { Edit, useForm } from "@refinedev/mui";
import { Typography } from "@mui/material";

export const ProductEdit = () => {
const invalidate = useInvalidate();
const { open } = useNotification();

const {
saveButtonProps,
refineCore: { queryResult, formLoading },
} = useForm();

const selectedProduct = queryResult?.data?.data;

const handleDelete = async (id: number) => {
const confirmDelete = window.confirm(
`ID가 ${id}인 항목을 삭제하시겠습니까?`
);
if (!confirmDelete) {
return;
}

console.log(`ID가 ${id}인 항목을 삭제합니다.`);
try {
const response = await dataProvider.default.removeDetail({
resource: 'products',
id: id,
variables: { id: id },
});
console.log('삭제 성공:', response);

// Invalidate the products list and show a success notification
invalidate({
resource: "products",
invalidates: ["list"],
});

open({
type: "success",
message: "Product successfully deleted",
});

// Optionally, navigate to the list page
// navigate("/products");
} catch (error) {
console.error('삭제 중 오류 발생:', error);
open({
type: "error",
message: "Error occurred while deleting the product",
});
}
};
return (
<Edit
title={
<Typography variant="h5">{selectedProduct?.product_name}</Typography>
}
isLoading={formLoading}
saveButtonProps={saveButtonProps}
footerButtons={() => <></>}
>
{/* Your form fields go here */}
</Edit>
);
};
import { useInvalidate, useNotification } from "@refinedev/core";
import { Edit, useForm } from "@refinedev/mui";
import { Typography } from "@mui/material";

export const ProductEdit = () => {
const invalidate = useInvalidate();
const { open } = useNotification();

const {
saveButtonProps,
refineCore: { queryResult, formLoading },
} = useForm();

const selectedProduct = queryResult?.data?.data;

const handleDelete = async (id: number) => {
const confirmDelete = window.confirm(
`ID가 ${id}인 항목을 삭제하시겠습니까?`
);
if (!confirmDelete) {
return;
}

console.log(`ID가 ${id}인 항목을 삭제합니다.`);
try {
const response = await dataProvider.default.removeDetail({
resource: 'products',
id: id,
variables: { id: id },
});
console.log('삭제 성공:', response);

// Invalidate the products list and show a success notification
invalidate({
resource: "products",
invalidates: ["list"],
});

open({
type: "success",
message: "Product successfully deleted",
});

// Optionally, navigate to the list page
// navigate("/products");
} catch (error) {
console.error('삭제 중 오류 발생:', error);
open({
type: "error",
message: "Error occurred while deleting the product",
});
}
};
return (
<Edit
title={
<Typography variant="h5">{selectedProduct?.product_name}</Typography>
}
isLoading={formLoading}
saveButtonProps={saveButtonProps}
footerButtons={() => <></>}
>
{/* Your form fields go here */}
</Edit>
);
};
Here are the key changes and explanations: 1. We import useInvalidate and useNotification hooks from @refinedev/core. These hooks will help us refresh the data and show notifications respectively. 2. Inside the component, we initialize these hooks:
const invalidate = useInvalidate();
const { open } = useNotification();

const invalidate = useInvalidate();
const { open } = useNotification();

3. After successful deletion, instead of reloading the page, we use the invalidate function:
invalidate({
resource: "products",
invalidates: ["list"],
});

invalidate({
resource: "products",
invalidates: ["list"],
});

This tells refine to refresh the list of products, effectively updating the UI without a full page reload. 4. We use the open function from useNotification to show success or error messages to the user:
open({
type: "success",
message: "Product successfully deleted",
});

open({
type: "success",
message: "Product successfully deleted",
});

5. Optionally, you can navigate to the list page after deletion if you're not already there:
// Uncomment this line if you want to navigate to the list page after deletion
// navigate("/products");

// Uncomment this line if you want to navigate to the list page after deletion
// navigate("/products");

This approach provides a smoother user experience by refreshing only the necessary data and providing feedback through notifications. It's also more efficient than reloading the entire page. For more information on data invalidation in refine, you can refer to the useInvalidate documentation. Remember to adjust the resource name and other details according to your specific implementation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1184365192482652173> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?