【发布时间】:2020-06-26 17:34:59
【问题描述】:
目标 - 我有一个用于更新产品详细信息的表单。 我想在提交表单时重定向到主页。
问题是我将表单数据从我的Form 组件发送到主要的App 组件以更新产品列表。产品处于我的App 状态,并作为道具传递给我的Form,这会导致Form 组件的重新渲染。
Form 的状态标志在构造函数中设置为 false:toHome: false。我的计划是在标志设置为 true 时利用 react-router 的 Redirect 触发。
在EditForm handleSubmit 方法中有一个setState({ toHome: true })。但是handleSubmit 中的ALSO 是更新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
【问题讨论】:
-
你能提供小提琴或代码吗?
-
已添加代码,干杯。
标签: javascript reactjs forms submit