I'm trying to submit a form with react & typescript but keep getting errors.
My terminal outputs this error Type 'File | undefined' is not assignable to type 'string | number | readonly string[] | undefined' and if I try to upload a file the website crashes with this warning and error.
Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string. at HTMLInputElement.set [as value]
-- EDIT --
So after debugging for a while I have discovered that if I just pass an empty string into the value attribute then the form submits and my image / file is processed and works fine. So the issue lyes with the setting of the value attribute which mean it's this error I need to fix! Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string. at HTMLInputElement.set [as value]
I have the following input component
import React, { useRef } from "react"; import { styled } from "../../../stitches.config"; const Input = styled("input", { width: "100%", height: "45px", background: "$white", color: "$black", textIndent: "10px", border: "1px solid $grey", borderRadius: "5px", paddingRight: "10px", }); interface Props extends React.InputHTMLAttributes<HTMLInputElement> { onChange: React.ChangeEventHandler<HTMLInputElement>; } export default ({ type, name, value, required, onChange }: Props) => { const input = useRef<HTMLInputElement>(null); return ( <Input type={type} name={name} value={value} ref={input} required={required} onChange={(e) => onChange(e)} /> ); }; My form component looks like this
interface Props { auth: any; } interface FormProps { title: string; intro: string; content: string; image: File | undefined; published_date: string; } const Create = ({ auth }: Props) => { const { data, setData, processing, post, errors } = useForm<FormProps>({ title: "", intro: "", content: "", image: undefined, published_date: "", }); const handleFile = (e: React.ChangeEvent<HTMLInputElement>) => { if (e.target.files) { setData("image", e.target.files[0]); console.log(data.image, " image"); } }; const onSubmit = (e: React.SyntheticEvent) => { e.preventDefault(); post("/admin/blogs/create", { preserveScroll: true, }); }; return ( <Authenticated auth={auth} css={{ background: "$light" }}> <Container css={{ maxWidth: "1200px", py: "100px" }}> <Heading size="charlie">Create a post</Heading> <Errors errors={errors} /> <form onSubmit={onSubmit} noValidate> .... <Row> <Label input={"image"} value={"Image"} required={true}> <Input type="file" name="image" value={data.image} required={true} onChange={handleFile} /> {errors.image && ( <InputError error={errors.image} /> )} </Label> </Row> <Row> <Button processing={processing} type={"submit"} color={"primary"} > Publish </Button> </Row> </form> </Container> </Authenticated> ); }; export default Create;
useForm()set the props to the component's state?datastate. Sorry forgot to mention that I'm using inertia.js form helper inertiajs.com/forms