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