Formik: How to set initial values to Field from Redux store state in Formik?

Created on 16 Dec 2018  路  9Comments  路  Source: formium/formik

鉂換uestion

Seriously, for immediate help, just ask your question on the #formik channel on Reactiflux.

stale

Most helpful comment

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 using withFormik() function and paste mapPropsToValues: ({initialValues}) => initialValues as option to the withFormik() function. It works for me.

@roman-pauk Could you provide an example please? :)

All 9 comments

@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 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 using withFormik() function and paste mapPropsToValues: ({initialValues}) => initialValues as option to the withFormik() 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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dearcodes picture dearcodes  路  3Comments

najisawas picture najisawas  路  3Comments

pmonty picture pmonty  路  3Comments

jaredpalmer picture jaredpalmer  路  3Comments

sibelius picture sibelius  路  3Comments