javascriptreactjsurlhttp-redirectreact-hooks

Dynamic URL query redirect on action in React


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;

Solution

  • 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.