Pulling data from supabase, using <Controller /> with a column that's an array?

Hello, I have the following setup:
import { useForm } from "@refinedev/react-hook-form";

const {
saveButtonProps,
refineCore: { query, formLoading, onFinish },
handleSubmit,
register,
control,
formState: { errors }
} = useForm<Selection>({
refineCoreProps: {
meta: {
select: "*, category_id(*), exam(*), exam_section(*)",
},
},
});

const questionData = query?.data?.data;
import { useForm } from "@refinedev/react-hook-form";

const {
saveButtonProps,
refineCore: { query, formLoading, onFinish },
handleSubmit,
register,
control,
formState: { errors }
} = useForm<Selection>({
refineCoreProps: {
meta: {
select: "*, category_id(*), exam(*), exam_section(*)",
},
},
});

const questionData = query?.data?.data;
questionData.choices is an array of strings. I have:
<FormGroup>
{questionData?.choices.map((choice: string, index: number) => (
<TextField
key={index}
{...register(`choices.[${index}]`, {
required: "This field is required",
})}
defaultValue={choice}
error={!!(errors as any)?.choices?.[index]}
helperText={(errors as any)?.choices?.[index]?.message}
margin="normal"
fullWidth
slotProps={{ inputLabel: { shrink: true } }}
type="text"
label={`Choice ${index + 1}`}
name={`choices.[${index}]`}
/>
))}
</FormGroup>
<FormGroup>
{questionData?.choices.map((choice: string, index: number) => (
<TextField
key={index}
{...register(`choices.[${index}]`, {
required: "This field is required",
})}
defaultValue={choice}
error={!!(errors as any)?.choices?.[index]}
helperText={(errors as any)?.choices?.[index]?.message}
margin="normal"
fullWidth
slotProps={{ inputLabel: { shrink: true } }}
type="text"
label={`Choice ${index + 1}`}
name={`choices.[${index}]`}
/>
))}
</FormGroup>
But something tells me this isn't going to update each question choice appropriately.
6 Replies
kapa.ai
kapa.ai2mo ago
Hi @Strange. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the information provided in the knowledge sources, I can offer some guidance on handling array data with React Hook Form and the <Controller /> component in refine, particularly when working with Supabase as a data provider. Your current approach using register for each choice field is close, but you're right to suspect it might not update each choice appropriately. When dealing with array fields in React Hook Form, it's generally recommended to use the useFieldArray hook or the <Controller /> component for more complex scenarios. Here's a suggested approach using <Controller />:
import { useForm, useFieldArray, Controller } from "@refinedev/react-hook-form";
import { TextField, FormGroup } from "@mui/material";

const {
saveButtonProps,
refineCore: { query, formLoading, onFinish },
control,
formState: { errors }
} = useForm<Selection>({
refineCoreProps: {
meta: {
select: "*, category_id(*), exam(*), exam_section(*)",
},
},
});

const { fields, append, remove } = useFieldArray({
control,
name: "choices",
});

const questionData = query?.data?.data;

// In your JSX:
<FormGroup>
{fields.map((field, index) => (
<Controller
key={field.id}
control={control}
name={`choices.${index}`}
defaultValue={questionData?.choices[index] || ""}
rules={{ required: "This field is required" }}
render={({ field }) => (
<TextField
{...field}
error={!!errors.choices?.[index]}
helperText={errors.choices?.[index]?.message}
margin="normal"
fullWidth
slotProps={{ inputLabel: { shrink: true } }}
type="text"
label={`Choice ${index + 1}`}
/>
)}
/>
))}
</FormGroup>
import { useForm, useFieldArray, Controller } from "@refinedev/react-hook-form";
import { TextField, FormGroup } from "@mui/material";

const {
saveButtonProps,
refineCore: { query, formLoading, onFinish },
control,
formState: { errors }
} = useForm<Selection>({
refineCoreProps: {
meta: {
select: "*, category_id(*), exam(*), exam_section(*)",
},
},
});

const { fields, append, remove } = useFieldArray({
control,
name: "choices",
});

const questionData = query?.data?.data;

// In your JSX:
<FormGroup>
{fields.map((field, index) => (
<Controller
key={field.id}
control={control}
name={`choices.${index}`}
defaultValue={questionData?.choices[index] || ""}
rules={{ required: "This field is required" }}
render={({ field }) => (
<TextField
{...field}
error={!!errors.choices?.[index]}
helperText={errors.choices?.[index]?.message}
margin="normal"
fullWidth
slotProps={{ inputLabel: { shrink: true } }}
type="text"
label={`Choice ${index + 1}`}
/>
)}
/>
))}
</FormGroup>
This approach uses the useFieldArray hook to manage the array of choices and the <Controller /> component to handle each choice input. This should properly update each choice and maintain the array structure. For more information on using <Controller /> and useFieldArray with React Hook Form in refine, you can refer to the following resources: 1. Dynamic Forms with React Hook Form 2. React Hook Form Validation with Complete Examples Additionally, when working with Supabase and array columns, you might need to adjust your data provider or form submission logic. The Supabase data provider in refine supports array operations, but you may need to specify the select option in your meta object to ensure you're fetching and updating the array data correctly. You can find more information about this in the Supabase Data Provider documentation. If you encounter any issues with updating array data in Supabase, you might need to adjust your onFinish logic or use the mutate function from useCreate or useUpdate hooks directly, as discussed in this GitHub issue. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@812403974997147658> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
conscious-sapphire
conscious-sapphireOP2mo ago
christ almighty this AI
No description
conscious-sapphire
conscious-sapphireOP2mo ago
okay well. that tells me what work needs to be done @kapa.ai useFieldArray() is not a hook that exists. you hallucinated it.
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize for the confusion in my previous response. You are correct to point out my mistake, and I thank you for bringing this to my attention. Let me provide a correct answer based on the information available in the knowledge sources. You are right that I made an error in mentioning useFieldArray(). This hook is actually part of the react-hook-form library, not @refinedev/react-hook-form. I should have been more careful in verifying the information before including it in my response. According to the knowledge sources, refine does use React Hook Form, and the useFieldArray() hook is indeed a valid part of React Hook Form. This is evidenced in the following sources: 1. Dynamic Forms with React Hook Form 2. Large Forms in React Hook Form with useFieldArray() In the context of refine, you would typically import useFieldArray from react-hook-form, not from @refinedev/react-hook-form. Here's the correct way to import and use useFieldArray:
import { useForm } from "@refinedev/react-hook-form";
import { useFieldArray } from "react-hook-form";
import { useForm } from "@refinedev/react-hook-form";
import { useFieldArray } from "react-hook-form";
I apologize again for the confusion in my previous response. Thank you for your attention to detail, as it helps maintain the accuracy of the information provided. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@812403974997147658> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?