I've never used Formik before, but hearing positive things on the net it sounds like this is a great solution compared to rolling own...which I usually try to do.
The docs for Formik have a simple, single instance of some of their attributes, like initialValues
and validationSchema
. However, I need to make this reusable, since I have 2 versions of this in my app. So i want to pass in the fields as props, then create the initialValues
as a form of state. This is OK, yes?
However, nothing renders...the value, errors
params shown in the documents, always shows as undefined
. Why is this? The state is updated and therefore, I assume the initialValues
will update the values
object. Scope inside the render
method does not allow me to be able to use this.state.initial
for example...
Errors object remains undefined, but I thought it should at least exist?
Basically, I have a Parent component that is rending inner components, one of which is a form group. So I am passing the array of fields, and a schema object to the container of Formik component like so:
const newCompanyFields = ["name", "address", "revenue", "phone"];
<Card
headerText="Create New Company"
id="new-company"
renderWith={() => (
<React.Fragment>
<div className="header">Add Company</div>
<Forms fields={newCompanyFields} schema={NewCompanySchema} />
</React.Fragment>
)}
/>
Then, inside the <Forms>
component, we will create instance of Formik like so:
class Forms extends Component {
state = {
initial: {}
};
componentDidMount() {
// we need to get the list of fields and setState to be used by Formik below
if (this.props.fields) {
let initialItems = {};
this.props.fields.forEach(item => {
return (initialItems[item] = "");
});
this.setState({ initial: initialItems });
}
}
render() {
return (
<StyledForms>
<Formik
initialValues={this.state.initial}
validationSchema={this.props.schema}
onSubmit={values => {
console.log(values, " submitted");
}}
render={({
values,
errors,
touched,
handleBlur,
handleChange,
handleSubmit,
isSubmitting
}) => (
<Form>
<FieldArray
name="field-company"
render={() => (
<div>
{values &&
Object.keys(values).map((field, index) => (
<div key={index}>
<Field name={field} />
{errors[field] && touched[field] ? (
<div>{errors[field]}</div>
) : null}
</div>
))}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</div>
)}
/>
</Form>
)}
/>
</StyledForms>
);
}
Link to Console screenshot: https://screencast.com/t/Pt7YOxU1Oq57
Thank you for clarification.
UPDATE If I update my initialValues attribute to NOT rely on component state, it works.
// assume ComponentDidMount from above is removed now
const getInitialValues = passedFields => {
let initialItems = {};
passedFields.forEach(item => {
return (initialItems[item] = "");
});
return initialItems;
};
<Formik
initialValues={getInitialValues(this.props.fields)}
...
/>
Is this expected?