title: Redirect React form component on submit. React Router v5.1
body: <p><strong>The goal</strong> - I have a form that is used to update product details.
  I want to redirect to home on form submit.</p>
  
  <p><strong>The problem</strong> is that I'm sending form data up from my <code>Form</code> component to the main <code>App</code> component to update the list of products. The products are in my <code>App</code> state, and passed as a prop to my <code>Form</code>, which causes a re-render of the <code>Form</code> component.</p>
  
  <p><code>Form</code> has a flag in state that is set to false in the constructor: <code>toHome: false</code>. My plan being to utilise react-router's <code>Redirect</code> to fire when the flag is set to true.</p>
  
  <p>In the <code>EditForm</code> handleSubmit method there's a <code>setState({ toHome: true })</code>. But ALSO in handleSubmit is the method (passed from <code>App</code> as a prop) to update the products in <code>App</code> state. </p>
  
  <p><strong>TLDR</strong> -> <code>Form</code> handleSubmit updates products -> <code>Form</code> re-renders -> redirect flag (<code>toHome</code>) set to false in constructor -> redirect never happens. </p>
  
  <p>I have the same problem even if I want to add a short success message. I've been stuck on this for wayyy too long.</p>
  
  <p><code>EditForm.js</code></p>
  
  <pre><code>import React, { Component } from 'react'
  import { Link, Redirect } from 'react-router-dom'
  import PropTypes from 'prop-types'
  
  class EditForm extends Component {
    constructor(props) {
      super(props)
      this.state = {
        product: {
          id: '',
          name: '',
          description: '',
          price: {
            base: '',
            amount: ''
          },
          relatedProducts: []
        },
        productIndex: '',
        toHome: false
      }
    }
  
    componentDidMount() {
      const { productId, allProducts } = this.props
      const thisProduct = this.findProduct(productId, allProducts)
      const thisIndex = this.findIndex(productId, allProducts)
  
      this.setState({ product: { ...thisProduct }, productIndex: thisIndex })
    }
  
    .........
  
    handleSubmit(e) {
      e.preventDefault()
      const newAllProducts = this.mergeProducts()
  // this is the method that's firing the re-render
      this.props.updateProducts(newAllProducts)
  // and here is the ill-fated setState
      this.setState({ toHome: true })
    }
  
    render() {
      const { id, name, description, price, toHome } = this.state.product
      console.log(this.state.toHome)
      if (toHome) {
        return &lt;Redirect to="/" /&gt;
      }
  
      return (
        &lt;div className="edit-form"&gt;
         ....form...
          &lt;/div&gt;
        &lt;/div&gt;
      )
    }
  }
  
  EditForm.propTypes = {
    productId: PropTypes.number.isRequired,
    allProducts: PropTypes.array.isRequired,
    userCurrency: PropTypes.string.isRequired,
    updateProducts: PropTypes.func.isRequired
  }
  
  export default EditForm
  </code></pre>
  
  <p><code>App.js</code></p>
  
  <pre><code>import React, { Component } from 'react'
  import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
  
  import ProductList from './ProductList'
  import SingleProduct from './SingleProduct'
  import Header from './Header'
  import EditForm from './EditForm'
  import Footer from './Footer'
  
  import allProducts from '../data/products.json'
  import '../scss/index.scss'
  
  class App extends Component {
    constructor() {
      super()
  
      this.state = {
        selectedCurrency: 'AUD',
        products: []
      }
    }
  
    componentDidMount() {
      this.setState({
        products: this.getLocalProducts()
      })
    }
  
    // Checks localStorage for existing product data.
    // If none, initiates localStorage with raw products data
    // and returns raw products to be added to state.
    getLocalProducts() {
      const localData = localStorage.getItem('allProducts')
      if (localData !== 'undefined' &amp;&amp; localData !== null) {
        return JSON.parse(localData)
      } else {
        localStorage.setItem('allProducts', JSON.stringify(allProducts))
        return allProducts
      }
    }
  
    // Updates localStorage and state.
    updateProducts = data =&gt; {
      localStorage.setItem('allProducts', JSON.stringify(data))
      this.setState({ products: data })
    }
  
    clearRedirect = () =&gt; {
      this.setState({ redirect: false })
    }
  
    handleCurrencyChange(e) {
      this.setState({ selectedCurrency: e.value })
    }
  
    render() {
      const { selectedCurrency, products } = this.state
  
      return (
        &lt;Router&gt;
          &lt;div className="app"&gt;
            &lt;Header
              handleChange={e =&gt; this.handleCurrencyChange(e)}
              userCurrency={selectedCurrency}
            /&gt;
            &lt;Switch&gt;
              &lt;Route
                path="/products/:id/edit"
                component={({ match }) =&gt; (
                  &lt;EditForm
                    productId={parseInt(match.params.id)}
                    userCurrency={selectedCurrency}
                    allProducts={products}
                    updateProducts={this.updateProducts}
                  /&gt;
                )}
              /&gt;
              &lt;Route
                path="/products/:id"
                component={({ match }) =&gt; (
                  &lt;SingleProduct
                    productId={parseInt(match.params.id)}
                    allProducts={this.getLocalProducts()}
                    userCurrency={selectedCurrency}
                  /&gt;
                )}
              /&gt;
              &lt;Route
                path="/"
                exact
                component={() =&gt; (
                  &lt;ProductList
                    allProducts={products}
                    userCurrency={selectedCurrency}
                  /&gt;
                )}
              /&gt;
            &lt;/Switch&gt;
            &lt;Footer /&gt;
          &lt;/div&gt;
        &lt;/Router&gt;
      )
    }
  }
  
  export default App
  </code></pre>