I’ll try to explain as best as I can.
I’m trying to send an array of strings along some other data to the BE.
But before submitting, I want to see the messages display in the UI as I keep adding them when I click “Enter” or the “Add” button.
This is the component for the messages:
export const CreateMessage = () => {
const {
control,
register,
formState: { errors },
setValue,
getValues,
} = useFormContext<FormFields>();
const currentUserEmail = some email
const [messages, setMessages] = useState<string[]>([]);
const [currentMessage, setCurrentMessage] = useState<string>('');
const handleAddMessage = () => {
if (currentMessage.trim() !== '') {
setMessages([...messages, currentMessage.trim()]);
setCurrentMessage('');
}
setValue('messages', messages);
};
const handleRemoveMessage = (index: number) => {
setMessages(messages.filter((_, i) => i !== index));
};
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleAddMessage();
}
};
return (
<Box>
<FormControl isInvalid={Boolean(errors.messages)}>
<FormLabel>Messages:</FormLabel>
<InputGroup>
<Textarea
rows={6}
{...register('messages', {
maxLength: {
value: 500,
message: 'Message must be at most 500 characters',
},
minLength: {
value: 3,
message: 'Message must be at least 3 characters',
},
})}
onKeyDown={handleKeyDown}
value={currentMessage}
onChange={(e) => setCurrentMessage(e.target.value)}
/>
</InputGroup>
{errors.messages && (
<FormErrorMessage>
{errors.messages && errors.messages.message}
</FormErrorMessage>
)}
</FormControl>
<Flex justifyContent="flex-end" mt={5}>
<Button size="md" onClick={handleAddMessage}>
Add
</Button>
</Flex>
<List mt={4} maxHeight="300px" overflowY="auto">
{messages.map((message, index) => (
<ListItem key={index}>
<Flex color="grey" justifyContent="space-between">
<Box>{currentUserEmail}</Box>
<Box>{dayjs().format('DD/MM/YYYY HH:mm')}</Box>
</Flex>
<Flex justifyContent="space-between">
<Box mt={2}>{message}</Box>
<IconButton
ml={2}
icon={<CloseOutlineIcon />}
onClick={() => handleRemoveMessage(index)}
aria-label="delete message"
/>
</Flex>
</ListItem>
))}
</List>
</Box>
);
};
This is a child component, in the parent component I have the submit plus other fields, etc. Works just fine. Is just this one that I can’t get it to work.
For some reason, I can console.log(getValue(‘messages’)) here and get the list, but when I submit the whole form, is not there.
This is the parent component:
export const CreateBrokerFeeForm = () => {
const submitForm = (data: FormFields) => {
const formDTO = mapperFormToDto(
data
);
onSubmit(formDTO);
};
return (
<form noValidate onSubmit={methods.handleSubmit(submitForm)}>
<FormProvider {...methods}>
<Grid templateColumns="repeat(3, 1fr)" gap={10}>
<GridItem colSpan={2}>
Some other forms
</GridItem>
<GridItem colSpan={1}>
<CreateJournalMessage />
</GridItem>
</Grid>
</FormProvider>
</form>
);
};
And the mapperFormToDto:
export const mapperFormToDto = (
formData: FormFields
) => {
const { messages } = formData
return {
...some formData,
messages: messages,
};
};
I simplified for sensitive information, but let me know if you need more stuff.
For clarity, I’m using chakra ui and react hook form
I tried different approaches but I can’t seem to get it to work.
I was told I might need to create another form. Basically a form within a form or something like that, but not sure if this is the best approach.
Mario Garcia Pinan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.