提交时重定向 React 表单组件。反应路由器 v5.1

Redirect React form component on submit. React Router v5.1

目标 - 我有一个用于更新产品详细信息的表格。 我想在提交表单时重定向到主页。

问题 是我将表单数据从我的 Form 组件发送到主 App 组件以更新产品列表。产品处于我的 App 状态,并作为道具传递给我的 Form,这会导致 Form 组件重新渲染。

Form 有一个在构造函数中设置为 false 的状态标志:toHome: false。我的计划是利用 react-router 的 Redirect 在标志设置为 true 时触发。

EditForm handleSubmit 方法中有一个 setState({ toHome: true })。但是在 handleSubmit 中还有方法(作为道具从 App 传递)来更新处于 App 状态的产品。

TLDR -> Form handleSubmit 更新产品 -> Form 重新呈现 -> 重定向标志 (toHome) 设置为 false在构造函数中 - >重定向永远不会发生。

即使我想添加一个简短的成功消息,我也有同样的问题。我已经坚持这个太久了。

EditForm.js

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 <Redirect to="/" />
    }

    return (
      <div className="edit-form">
       ....form...
        </div>
      </div>
    )
  }
}

EditForm.propTypes = {
  productId: PropTypes.number.isRequired,
  allProducts: PropTypes.array.isRequired,
  userCurrency: PropTypes.string.isRequired,
  updateProducts: PropTypes.func.isRequired
}

export default EditForm

App.js

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' && localData !== null) {
      return JSON.parse(localData)
    } else {
      localStorage.setItem('allProducts', JSON.stringify(allProducts))
      return allProducts
    }
  }

  // Updates localStorage and state.
  updateProducts = data => {
    localStorage.setItem('allProducts', JSON.stringify(data))
    this.setState({ products: data })
  }

  clearRedirect = () => {
    this.setState({ redirect: false })
  }

  handleCurrencyChange(e) {
    this.setState({ selectedCurrency: e.value })
  }

  render() {
    const { selectedCurrency, products } = this.state

    return (
      <Router>
        <div className="app">
          <Header
            handleChange={e => this.handleCurrencyChange(e)}
            userCurrency={selectedCurrency}
          />
          <Switch>
            <Route
              path="/products/:id/edit"
              component={({ match }) => (
                <EditForm
                  productId={parseInt(match.params.id)}
                  userCurrency={selectedCurrency}
                  allProducts={products}
                  updateProducts={this.updateProducts}
                />
              )}
            />
            <Route
              path="/products/:id"
              component={({ match }) => (
                <SingleProduct
                  productId={parseInt(match.params.id)}
                  allProducts={this.getLocalProducts()}
                  userCurrency={selectedCurrency}
                />
              )}
            />
            <Route
              path="/"
              exact
              component={() => (
                <ProductList
                  allProducts={products}
                  userCurrency={selectedCurrency}
                />
              )}
            />
          </Switch>
          <Footer />
        </div>
      </Router>
    )
  }
}

export default App

我认为您需要对 impl 进行一些澄清,因此请提供 fiddle 或其他信息。

与此同时,我猜您需要在提交表单时重定向?

如果是这样,

import { useHistory } from "react-router-dom"; 

并做

  let history = useHistory();
  function handleSubmit() {
    props.handleSubmit() // the one that comes from your App
    history.push("/home");
  }

一旦您提供更多信息,我将相应地编辑答案。

改为使用 this.props.history.push('/') 重定向到您的主页