DEV Community

loading...
Cover image for Handling React Form Submit with Redirect & Async/Await for Beyond Beginners

Handling React Form Submit with Redirect & Async/Await for Beyond Beginners

Brad Beggs
Curious and Persistent.
・3 min read

Who This Is for

  • You have a functioning async/await fetch helper function to POST/GET/PATCH/etc.
  • Upon successful submission, you want to redirect the user to another page.
  • You are using functional components (i.e. not a class component).
  • You have a working form, meaning, at a minimum, you can console.log(someFormData) inside the handleSubmit() function.
  • Already using React-Router-Dom for navigation and links

Step 1 - Your async/await is in a Helper Function/File

Place your FETCH function(s) in an ./api/fetch.js file for easy reuse.

Step 2 - Call Your Helper Function From handleSubmit()

For this tutorial, I’m using a POST function call inside the handleSubmit():

function handleSubmit(event){
    event.preventDefault()

    let token = // unimportant code handling getting a token 

   // helper function from the fetch API class, located in another file
    Api.addIncidentAsync(
     token,  
     values.title  // from state using hooks
     )
      // can the redirect go here??
    }
Enter fullscreen mode Exit fullscreen mode

Though the nested fetch function inside Api.addIncidentAsync() won’t return a pendingPromise because of async/await, the Api.addIncidentAsync() itself does return a pendingPromise since Javascript can/does run asynchronously.

This means if your redirect url is created from the FETCH response, your redirect will execute before the Api.addIncidentAsync() resolves since Javascript runs both Api.addIncidentAsync() and redirect effectively at the same time.

TL:DR No, you can’t create a dynamic URL redirect in the above comment location. It is a timing issue between a redirect and Api.addIncidentAsync() resolving.

Step 3 - Chain .then() to Your FETCH Helper Function

To fix the timing issue, add .then() to the end of your helper function.

Now the handleSubmit() looks like this:

function handleSubmit(event){
    event.preventDefault()

    let token = // unimportant code for getting a token 

    // helper function from the fetch API class 
    Api.addIncidentAsync(
      token,  
      value.title  // from state
     ).then(response => {
         // redirect code here
      }
    }
Enter fullscreen mode Exit fullscreen mode

The code in .then() only runs once the promise resolves from Api.addIncidentAsync().

Step 4 - React-Router-Dom Hooks: useHistory() to history.push() a Redirect

In React 16.8 useHistory() hook from React-Router-Dom lets you manipulate the browser DOM history. Read more on the History object

useHistory() requires a React Component (arrow function or regular function with CapitalizedName), not a class component, to work (per the Rules of Hooks)

import { useHistory } from "react-router-dom";
import Api from '../api';

function IncidentForm(){
  const [values, setValues] = useState(initialValues); // using hooks for form state

  let history = useHistory();  // declare here, inside a React component. 

  const handleInputChange = (event)=>{ 
    // unimportant code
  }

  function handleSubmit(event){
    event.preventDefault()

    let token =  // unimportant code for getting a token 


    Api.addIncidentAsync(
      token,
      value.title  // from state 
     ).then(response => {
       let url = response.data.id + //string to build URL
       history.push(url)  // redirect
      })
    }

// more form code below, not included 
Enter fullscreen mode Exit fullscreen mode

Step 5 - Error Handling

No error handling is included for simplicity. Make sure to include error handling in your code.

Feedback?

Have thoughts on async/await or the above implementation? In particular, is it possible to drop the use of .then()?

If so, drop a note. I'd love to hear and see your examples, explanations, and other details to clarify how/why/when.

Resources

React Components
React Router Hooks
Rules of Hooks
Functional Components vs Classes
Async/Await & Promise - Straightforward Explanation

Discussion (2)

Collapse
rickystam profile image
Ricky Stam

A nice addition to your example would be to show how to handle 302 Redirect Http response from server

Collapse
brad_beggs profile image
Brad Beggs Author

That'll be a brave new frontier for me; haven't yet dealt with a 302 server response.