I have an input type=”file” in a form, which when submitted, should return an object with image:FileList with the actual image file submitted, but somehow the file just isn’t showing. No ERROR was logged. Everything seems working fine but the file just won’t show up…
import FormButton from '../../ui/FormButton';
import Label from '../../ui/Label';
import useEditMenu from './useEditMenu';
import useAddMenu from './useAddMenu';
import { useForm } from 'react-hook-form';
import { useState } from 'react';
import { ImCross } from 'react-icons/im';
const inputCommonStyle =
' w-full rounded-xl bg-stone-700 p-1 px-2 text-stone-300 focus:outline-none focus:ring-2 focus:ring-stone-400';
function MenuForm({ onEdit, toggleEdit, toggleAdd, menuItem = {} }) {
//menuItem={} to prevent error due to "destructuring failure"
const { dish_name, menu_type, price, ingredients, image, id } = menuItem;
const { isEditing, handleEdit, isEditError, editError } = useEditMenu();
const { isAdding, handleAdd, isAddError, addError } = useAddMenu();
const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm();
function onSubmit(data) {
console.log(data.image);
onEdit ? handleEdit(data) : handleAdd(data);
onEdit ? toggleEdit() : reset();
}
const [inputLength, setInputLength] = useState(0);
function handleChange(e) {
const value = e.target.value;
setInputLength(value.length);
}
return (
<form
className="h-11/12 w-11/12 rounded-md border-2 border-stone-400 p-2 text-stone-300"
onSubmit={handleSubmit(onSubmit)}
>
<div className="flex justify-end">
<span
className="cursor-pointer text-stone-700"
onClick={() => (onEdit ? toggleEdit() : toggleAdd())}
>
<ImCross className="text-stone-400" />
</span>
</div>
<Label htmlFor="id"> Menu Number* </Label>
<input
type="text"
className={`${inputCommonStyle}`}
disabled={isEditing || isAdding}
id="id"
defaultValue={id}
{...register('id', {
required: 'Please enter a number...',
})}
/>
{errors.id && <p className="text-pink-800">{errors.id.message}</p>}
<Label htmlFor="menu_type"> Menu Category* </Label>
<input
type="text"
className={`${inputCommonStyle}`}
id="menu_type"
defaultValue={menu_type}
disabled={isEditing || isAdding}
{...register('menu_type', {
required: 'Please enter a category...',
})}
/>
{errors.menu_type && (
<p className="text-pink-800">{errors.menu_type.message}</p>
)}
<Label htmlFor="dish_name">Name*</Label>
<input
type="text"
className={`${inputCommonStyle}`}
id="dish_name"
defaultValue={dish_name}
disabled={isEditing || isAdding}
{...register('dish_name', {
required: 'Please enter a dish name...',
maxLength: {
value: 20,
message: 'Dish name should not exceed 20 characters',
},
})}
/>
{errors.dish_name && (
<p className="text-pink-800">{errors.dish_name.message}</p>
)}
<Label htmlFor="price">Price*</Label>
<input
type="text"
className={`${inputCommonStyle}`}
id="price"
defaultValue={price}
disabled={isEditing || isAdding}
{...register('price', {
required: 'Please enter a price...',
})}
/>
{errors.price && <p className="text-pink-800">{errors.price.message}</p>}
<Label htmlFor="ingredients">Ingredients</Label>
<textarea
className={`${inputCommonStyle} resize-none overflow-auto`}
id="ingredients"
rows="3"
defaultValue={ingredients}
disabled={isEditing || isAdding}
{...register('ingredients', {
maxLength: {
value: 100,
message: 'Ingredients list should not exceed 100 characters',
},
onChange: (e) => handleChange(e),
})}
></textarea>
<p className="text-sm font-light text-stone-400">
{`${inputLength}/100 characters`}
</p>
{errors.ingredients && (
<p className="text-pink-800">{errors.ingredients.message}</p>
)}
<Label htmlFor="image">Attach Image*</Label>
<input
type="file"
className={`${inputCommonStyle}`}
id="image"
accept="image/*"
// defaultValue={image}
disabled={isEditing || isAdding}
{...register('image', {
required: 'Please submit an image...',
})}
/>
{errors.image && <p className="text-pink-800">{errors.image.message}</p>}
<div className="space-x-3 self-end">
<FormButton> {onEdit ? 'Edit' : 'Submit'} </FormButton>
</div>
</form>
);
}
export default MenuForm;
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { addMenu } from '../../services/apiClients';
function useAddMenu() {
const queryClient = useQueryClient();
const {
isLoading: isAdding,
mutate: handleAdd,
isError: isAddError,
error: addError,
} = useMutation({
mutationFn: addMenu,
onSuccess: () => {
console.log('New menu added');
queryClient.invalidateQueries({ queryKey: ['menu'] });
},
onError: (err) => {
console.error(err);
},
});
return { isAdding, handleAdd, isAddError, addError };
}
export default useAddMenu;
export async function addMenu(menuItem) {
// const { dish_name, menu_type, ingredients } = menuItem;
console.log(menuItem)
I reviewed my code, but can’t seem to pinpoint the problem.
New contributor
Giuliana is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.