Seriously, for immediate help, just ask your question on the #formik channel on Reactiflux.
@jaredpalmer Hi Everyone, I can't set the initial values to the field from redux store as an object and set it into props from the parent container. I am struggling with this can anyone please?
Below is my code:
<h2>Example of code</h2>
<pre>
import React from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as homePageDetails from '../../actionCreators/HomePage';
import Basic from '../../components/formik';
This is my parent container:
class HomePage extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
componentDidMount() {
this.props.actions.getHomePage();
}
render() {
const { homepageData } = this.props;
const { Bannertext = '', User={}} = homepageData;
return (
<div className="Main">
<h2>{ Bannertext }</h2>
<Basic
user = {User}
/>
);
}
}
function mapStateToProps(state) {
const { homePageState } = state;
return {
homepageData: homePageState.homePageData || {},
isLoading: homePageState.isLoading,
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(homePageDetails, dispatch),
};
}
HomePage.propTypes = {
homepageData: PropTypes.object,
actions: PropTypes.object,
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(HomePage));
This is my child component:
import React from 'react';
import { Formik, Field, Form, ErrorMessage } from 'formik';
const Basic = ({ user, updateUser, onClose }) => {
return (
<div className="Main">
<Formik
initialValues={user}
onSubmit={(values, actions) => {
MyImaginaryRestApiCall(user.id, values).then(
updatedUser => {
actions.setSubmitting(false);
updateUser(updatedUser);
onClose();
},
error => {
actions.setSubmitting(false);
actions.setErrors(transformMyRestApiErrorsToAnObject(error));
actions.setStatus({ msg: 'Set some arbitrary status or data' });
}
);
}}
render={({ errors, status, touched, isSubmitting }) => (
<Form>
<Field type="email" name="email" />
<ErrorMessage name="email" component="div" />
{status && status.msg && <div>{status.msg}</div>}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</Form>
)}
/>
</Dialog>
</div>
);
};
export default Basic;
This is my object from response:
"User":{
"id":1,
"email":"[email protected]",
"password": "123",
"text":"Hi this is test"
}
</pre>
HI @navaswd. Try change some code. Hope it help.
render={({ errors, status, touched, isSubmitting, values }) => (
<Form>
<Field type="email" name="email" value={values.email} />
<ErrorMessage name="email" component="div" />
{status && status.msg && <div>{status.msg}</div>}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</Form>
)}
Thanks bro, But its not setting the initial values from the redux store.
@navaswd Oh sorry, I think I know what is wrong. In React lifecycle, componentDidMount will take after render. Maybe the first time rendering, the formik receive initialValue of user is {}. So they can not set value. Please try console.log the user the first time when formik render for testing
@DatNT96 Thanks, will I try it with receive props lifecycles? or any other method do you know?
Hi @navaswd . You can write a wrapper component and connect it to the store. Then paste the initial props to the form component, for example, it will be initialValues. Then create form component using withFormik() function and paste mapPropsToValues: ({initialValues}) => initialValues as option to the withFormik() function. It works for me.
Hi @navaswd . You can write a wrapper component and connect it to the store. Then paste the initial props to the form component, for example, it will be
initialValues. Then create form component usingwithFormik()function and pastemapPropsToValues: ({initialValues}) => initialValuesas option to thewithFormik()function. It works for me.
Hi @navaswd . You can write a wrapper component and connect it to the store. Then paste the initial props to the form component, for example, it will be
initialValues. Then create form component usingwithFormik()function and pastemapPropsToValues: ({initialValues}) => initialValuesas option to thewithFormik()function. It works for me.
@roman-pauk Could you provide an example please? :)
You can try to add enableReinitialize property to <Formik enableReinitialize> tag
This is how I got it working:
import * as Yup from 'yup'
import { withFormik } from 'formik'
import { connect } from 'react-redux'
import * as React from 'react'
import { Button } from 'react-native'
const mapStateToProps = (
state
) => ({
categories: state.formControls.categories
})
const mapDispatchToProps = (dispatch) => ({
updateRerenderKey: () => {
dispatch(updateRerenderKey())
}
})
class MyCustomComponent extends React.Component {
render() {
const {
values,
handleSubmit,
setFieldValue,
errors
} = this.props
return (
<Button onPress={handleSubmit} />
)}
}
const formikEnhancer = withFormik({
validationSchema: Yup.object().shape({
categories: Yup.array().required()
}),
enableReinitialize: true,
mapPropsToValues: (props) => ({
categories: props.categories
}),
handleSubmit: (values, { props }) => {
props.updateRerenderKey()
}
})(MyCustomComponent)
const MyCustomComponentConnected = connect(
mapStateToProps,
mapDispatchToProps
)(formikEnhancer)
export default MyCustomComponentConnected
Inside MyCustomComponent, props.categories is now taken from the Redux store, and <Button onPress={handleSubmit} /> now triggers props.updateRerenderKey() which dispatches a Redux action.
Most helpful comment
@roman-pauk Could you provide an example please? :)