I am attempting to use a redirect with a query from a form in React. I have tried numerous ways but cannot seem to get it to work. I am new to front end development on the whole so what seems fairly trivial is causing me some pain.
The point I currently have my application at is that the action is getting a null value from the form input as at runtime when the action is created the value is null. The input being the value of the element "image_link".
What is the best way to go about setting it so that the URL passed through is included in the query param. I will attach both the Form.js and UseForm.js below.
FORM.js
import useForm from "./UseForm";
const FORM_ENDPOINT = "https://ENDPOINT"; // TODO - update to the correct endpoint
const Form = () => {
const additionalData = {
sent: new Date().toISOString(),
};
const { handleSubmit, status, message } = useForm({
additionalData,
});
if (status === "success") {
return (
<>
<div className="text-2xl">Thank you!</div>
<div className="text-md">{message}</div>
</>
);
}
if (status === "error") {
return (
<>
<div className="text-2xl">Something bad happened!</div>
<div className="text-md">{message}</div>
</>
);
}
return (
<form
action={FORM_ENDPOINT+"?image_link="+document.getElementsByName("image_link").value}
onSubmit={handleSubmit}
method="POST"
>
<div className="pt-0 mb-3">
<input
type="text"
placeholder="Image Link"
name="image_link"
className="focus:outline-none focus:ring relative w-full px-3 py-3 text-sm text-gray-600 placeholder-gray-400 bg-white border-0 rounded shadow outline-none"
required
/>
</div>
{status !== "loading" && (
<div className="pt-0 mb-3">
<button
className="active:bg-blue-600 hover:shadow-lg focus:outline-none px-6 py-3 mb-1 mr-1 text-sm font-bold text-white uppercase transition-all duration-150 ease-linear bg-blue-500 rounded shadow outline-none"
type="submit"
>
Submit Image
</button>
</div>
)}
</form>
);
};
export default Form;
UseForm.js
import { useState } from "react";
async function useForm({ additionalData }) {
const [status, setStatus] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
setStatus('loading');
setMessage('');
const finalFormEndpoint = e.target.action;
const data = Array.from(e.target.elements)
.filter((input) => input.name)
.reduce((obj, input) => Object.assign(obj, { [input.image_link]: input.value }), {});
if (additionalData) {
Object.assign(data, additionalData);
}
fetch(finalFormEndpoint, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => {
if (response.status !== 200) {
throw new Error(response.statusText);
}
return response.json();
})
.then((response) => {
setMessage("The result is: " + response.body);
setStatus('success');
})
.catch((err) => {
setMessage(err.toString());
setStatus('error');
});
};
return { handleSubmit, status, message };
}
export default useForm;
UPDATE with SID suggestions
import useForm from "./UseForm";
import { useState } from "react";
const FORM_ENDPOINT = "https://ml-backend.wonderfulsea-73c97836.uksouth.azurecontainerapps.io/net/image/prediction/"; // TODO - update to the correct endpoint
const Form = () => {
// add this to your Form component before return ()
const [formEndpoint, setFormEndpoint] = useState(FORM_ENDPOINT);
const handleOnBlur = (event) => {
if(!event?.data?.value) {
alert('please enter a valid value');
}
setFormEndpoint(`${FORM_ENDPOINT}?image_link=${event?.data?.value}`);
}
const { handleSubmit, status, message } = useForm({
});
if (status === "success") {
return (
<>
<div className="text-2xl">Thank you!</div>
<div className="text-md">{message}</div>
</>
);
}
if (status === "error") {
return (
<>
<div className="text-2xl">Something bad happened!</div>
<div className="text-md">{message}</div>
</>
);
}
return (
<form
action={formEndpoint}
onSubmit={handleSubmit}
method="POST"
>
<div className="pt-0 mb-3">
<input
type="text"
placeholder="Image Link"
name="image_link"
onBlur={handleOnBlur}
className="focus:outline-none focus:ring relative w-full px-3 py-3 text-sm text-gray-600 placeholder-gray-400 bg-white border-0 rounded shadow outline-none"
required
/>
</div>
{status !== "loading" && (
<div className="pt-0 mb-3">
<button
className="active:bg-blue-600 hover:shadow-lg focus:outline-none px-6 py-3 mb-1 mr-1 text-sm font-bold text-white uppercase transition-all duration-150 ease-linear bg-blue-500 rounded shadow outline-none"
type="submit"
>
Submit an image
</button>
</div>
)}
</form>
);
};
export default Form;
You can listen to the onBlur
event of image_link
input and update your state when the input element looses its focus.
const FORM_ENDPOINT = "https://ENDPOINT"; // TODO - update to the correct endpoint
const Form = () => {
// add this to your Form component before return ()
const [formEndpoint, setFormEndpoint] = useState(FORM_ENDPOINT);
const handleOnBlur = (event) => {
if(!event.target.value) {
alert('please enter a valid value');
}
setFormEndpoint(`${FORM_ENDPOINT}?image_link=${event.target.value}`);
}
return (
<form
action={formEndpoint}
onSubmit={handleSubmit}
method="POST"
>
<div className="pt-0 mb-3">
<input
type="text"
placeholder="Image Link"
name="image_link"
onBlur={handleOnBlur}
className="focus:outline-none focus:ring relative w-full px-3 py-3 text-sm text-gray-600 placeholder-gray-400 bg-white border-0 rounded shadow outline-none"
required
/>
</div>
</form>
);
};
export default Form;
Should work this way.