Here's the template for a form I'm writing with Formik and react-bootstrap. I'm finding a very strange error: if I initialise my state with dummy data in the constructor, it works fine; but if I call setState with the exact same data in componentDidMount
to simulate an API call, it breaks horribly.
Specifically, I find that the state variable alertVehicles
array can have non-zero length, but the corresponding Formik values.alertVehicles
variable can be empty. Right now, the form as written renders no checkboxes. If I use alertVehicles
instead of values.alertVehicles
in my guard clause, then it blows up with an error 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;
I don't understand
componentDidMount
values.alertVehicles
doesn't appear to be in sync with alertVehicles
.Thanks in advance for any help.
We can reset the form by using the resetForm() method of formik. We can register it on the onClick event of the reset button.
Returns true if values are not deeply equal from initial values, false otherwise. dirty is a readonly computed property and should not be mutated directly.
it is very simple just do console. log(formik. values) and you will get all the values without submitting it.
For some reason this is Formik's default behaviour, and you need to supply the enableReinitialize
prop to override it:
https://github.com/jaredpalmer/formik/issues/811
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With