Formik 值不随状态更新
Formik values not updating with state
这是我用 Formik 和 react-bootstrap 编写的表单模板。我发现一个非常奇怪的错误:如果我在构造函数中使用虚拟数据初始化我的状态,它工作正常;但是如果我用 componentDidMount
中的完全相同的数据调用 setState 来模拟 API 调用,它就会崩溃。
具体来说,我发现状态变量alertVehicles
数组可以有非零长度,但是对应的Formik values.alertVehicles
变量可以为空。现在,所写的表单不呈现复选框。如果我在保护子句中使用 alertVehicles
而不是 values.alertVehicles
,那么它会因错误 Cannot read property 'selected' of undefined
.
而爆炸
import React, {Component} from 'react';
import Form from 'react-bootstrap/Form';
import { Formik } from 'formik';
import Button from 'react-bootstrap/Button';
class Alerts extends Component {
constructor(props) {
super(props);
this.loadAlertData = this.loadAlertData.bind(this);
this.state = {
alertRecipient: {},
alertId: '',
alertVehicles: []
}
}
componentDidMount(){
this.loadAlertData();
}
loadAlertData(){
// this will be an API call eventually, obviously.
// if this is initialised in the constructor then everything works!
this.setState( {
alertRecipient: {
name: 'Rob',
simNumber: '0123456789',
},
alertId: 1,
alertVehicles: [
{id: 1, vrn: 'vehicle A', selected: true },
{id: 2, vrn: 'vehicle B', selected: false },
{id: 3, vrn: 'vehicle C', selected: true }
]
})
}
render() {
const { alertRecipient, alertId, alertVehicles } = this.state;
return (
<>
<Formik
initialValues={{ alertRecipient, alertId, alertVehicles }}
onSubmit={ values => {
window.alert(JSON.stringify(values))
}
}
render={({values, handleChange, handleSubmit}) => (
<Form onSubmit={handleSubmit}>
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
name="alertRecipient.name"
value={values.alertRecipient.name}
onChange={handleChange}
/>
<Form.Label>Phone number</Form.Label>
<Form.Control
type="text"
name="alertRecipient.simNumber"
value={values.alertRecipient.simNumber}
onChange={handleChange}
>
</Form.Control>
<Form.Label>Vehicles</Form.Label>
{
//get an error if we just use alertVehicles.length here??
values.alertVehicles.length === 0 ? null : alertVehicles.map((veh, index) => (
<Form.Check type="checkbox"
key={veh.id}
label={veh.vrn}
name={`alertVehicles[${index}].selected`}
checked={values.alertVehicles[index].selected}
onChange={ handleChange }
/>
))
}
<Button type="submit">Save</Button>
</Form>
)
}
/>
</>
)
}
}
export default Alerts;
没看懂
- 为什么当我在构造函数中设置虚拟数据但在
componentDidMount
中设置虚拟数据时代码有效
- 为什么
values.alertVehicles
似乎与 alertVehicles
不同步。
在此先感谢您的帮助。
出于某种原因,这是 Formik 的默认行为,您需要提供 enableReinitialize
属性来覆盖它:
https://github.com/jaredpalmer/formik/issues/811
其实很有道理。大多数时候,您不想因为状态改变而破坏用户在表单上所做的事情。事实上,如果用户还没有触及任何东西,但之后你可能会想要。
无论哪种方式,他们都会给你控制它的标志...
这是我用 Formik 和 react-bootstrap 编写的表单模板。我发现一个非常奇怪的错误:如果我在构造函数中使用虚拟数据初始化我的状态,它工作正常;但是如果我用 componentDidMount
中的完全相同的数据调用 setState 来模拟 API 调用,它就会崩溃。
具体来说,我发现状态变量alertVehicles
数组可以有非零长度,但是对应的Formik values.alertVehicles
变量可以为空。现在,所写的表单不呈现复选框。如果我在保护子句中使用 alertVehicles
而不是 values.alertVehicles
,那么它会因错误 Cannot read property 'selected' of undefined
.
import React, {Component} from 'react';
import Form from 'react-bootstrap/Form';
import { Formik } from 'formik';
import Button from 'react-bootstrap/Button';
class Alerts extends Component {
constructor(props) {
super(props);
this.loadAlertData = this.loadAlertData.bind(this);
this.state = {
alertRecipient: {},
alertId: '',
alertVehicles: []
}
}
componentDidMount(){
this.loadAlertData();
}
loadAlertData(){
// this will be an API call eventually, obviously.
// if this is initialised in the constructor then everything works!
this.setState( {
alertRecipient: {
name: 'Rob',
simNumber: '0123456789',
},
alertId: 1,
alertVehicles: [
{id: 1, vrn: 'vehicle A', selected: true },
{id: 2, vrn: 'vehicle B', selected: false },
{id: 3, vrn: 'vehicle C', selected: true }
]
})
}
render() {
const { alertRecipient, alertId, alertVehicles } = this.state;
return (
<>
<Formik
initialValues={{ alertRecipient, alertId, alertVehicles }}
onSubmit={ values => {
window.alert(JSON.stringify(values))
}
}
render={({values, handleChange, handleSubmit}) => (
<Form onSubmit={handleSubmit}>
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
name="alertRecipient.name"
value={values.alertRecipient.name}
onChange={handleChange}
/>
<Form.Label>Phone number</Form.Label>
<Form.Control
type="text"
name="alertRecipient.simNumber"
value={values.alertRecipient.simNumber}
onChange={handleChange}
>
</Form.Control>
<Form.Label>Vehicles</Form.Label>
{
//get an error if we just use alertVehicles.length here??
values.alertVehicles.length === 0 ? null : alertVehicles.map((veh, index) => (
<Form.Check type="checkbox"
key={veh.id}
label={veh.vrn}
name={`alertVehicles[${index}].selected`}
checked={values.alertVehicles[index].selected}
onChange={ handleChange }
/>
))
}
<Button type="submit">Save</Button>
</Form>
)
}
/>
</>
)
}
}
export default Alerts;
没看懂
- 为什么当我在构造函数中设置虚拟数据但在
componentDidMount
中设置虚拟数据时代码有效
- 为什么
values.alertVehicles
似乎与alertVehicles
不同步。
在此先感谢您的帮助。
出于某种原因,这是 Formik 的默认行为,您需要提供 enableReinitialize
属性来覆盖它:
https://github.com/jaredpalmer/formik/issues/811
其实很有道理。大多数时候,您不想因为状态改变而破坏用户在表单上所做的事情。事实上,如果用户还没有触及任何东西,但之后你可能会想要。
无论哪种方式,他们都会给你控制它的标志...