Handling React Form Submit with Redirect & Async/Await for Beyond Beginners
Tags: react, javascript
Published: 2020-12-10 23:04:05



## 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()`: 
```javascript
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??
    }
```  
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:
```javascript
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
      }
    }
```
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](https://reactrouter.com/web/api/history) 

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

```javascript
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 
 ```
## 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](https://reactjs.org/docs/components-and-props.html)
[React Router Hooks](https://reactrouter.com/web/api/Hooks)
[Rules of Hooks](https://reactjs.org/docs/hooks-rules.html)
[Functional Components vs Classes](https://www.twilio.com/blog/react-choose-functional-components)
[Async/Await & Promise - Straightforward Explanation](https://dev.to/shoupn/javascript-fetch-api-and-using-asyncawait-47mp)