I am trying to send a post with fetch an API.
My fetch is working because it returns 200
and sends the request but it sends an empty form.
It cannot take the values in the form input. Where is my mistake and how can I fix it?
... const [contract, setContract] = useState(""); const form = useRef(null); const submit = (e) => { e.preventDefault(); const data = new FormData(form.current); fetch(process.env.REACT_APP_ENDPOINT + "user/me/contract", { method: "POST", body: data, headers: { "Content-Type": "application/json", Authorization: `Bearer ${localStorage.getItem("fray_access_token")}`, }, }) .then((res) => res.json()) .then((json) => setContract(json.contract)); }; return( ... <form ref={form} onSubmit={submit}> <Input required type="text" value={contract.name} onChange={(e) => setContract({ ...contract, name: e.target.value }) } /> <Input required type="text" value={contract.surname} onChange={(e) => setContract({ ...contract, surname: e.target.value }) } /> <Input required type="email" value={contract.emai} onChange={(e) => setContract({ ...contract, email: e.target.value }) } /> </form> ...)
Advertisement
Answer
[Update]:
You can either remove the application/json
header and let browser post the form data implicitly using the multipart/form-data
content-type :
const submit = (e) => { e.preventDefault(); const data = new FormData(form.current); fetch(process.env.REACT_APP_ENDPOINT + "user/me/contract", { method: "POST", body: data, headers: { Authorization: `Bearer ${localStorage.getItem("fray_access_token")}`, }, }) .then((res) => res.json()) .then((json) => setContract(json.contract)); };
As @Quentin pointed out, we cannot serialise FormData
using JSON.stringify
so it’s better to use explicit function to do it for you:
const serialize = (data) => { let obj = {}; for (let [key, value] of data) { if (obj[key] !== undefined) { if (!Array.isArray(obj[key])) { obj[key] = [obj[key]]; } obj[key].push(value); } else { obj[key] = value; } } return obj; } const submit = (e) => { e.preventDefault(); const data = new FormData(form.current); fetch(process.env.REACT_APP_ENDPOINT + "user/me/contract", { method: "POST", body: typeof data !== 'string' ? JSON.stringify(serialize(data)): data, headers: { "Content-Type": "application/json", Authorization: `Bearer ${localStorage.getItem("fray_access_token")}`, }, }) .then((res) => res.json()) .then((json) => setContract(json.contract)); };
More details : https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch