15

I am developing a dynamic form in React JS, when the user clicks on the Add button, the Register form is added to screen. In the Register form I am using formik for validation.

The form is dynamically adding successfully but whenever I start entering any input in the input box, I am getting the following error in the console:

Warning: A component is changing an uncontrolled input of type text to be 
controlled. Input elements should not switch from uncontrolled to controlled 
(or vice versa). Decide between using a controlled or uncontrolled input element 
for the lifetime of the component. 

I am not sure where it is wrong. Below is my dynamic form rendering code -

Account.js

import React, { Component } from 'react';
import axios from 'axios';
import {
    Card, CardBody, CardHeader,Button,Col, Row, Form, Container
} from 'reactstrap';
import { Formik, Field, ErrorMessage } from 'formik';
import WrapperForm from './WrapperForm'

class Account extends Component {

  state = {
    wrapperForm: [{}]
  }

  constructor(props) {
    super(props);
  }

  addUser = () => {
    this.setState((prevState) => ({
      wrapperForm: [...prevState.wrapperForm, {}],
    }));
  }

  render() {
    let { wrapperForm } = this.state
    return (
      <Form>
        <Container className="themed-container" fluid={true}>
          <button type="button" onClick={this.addUser}>Add User</button>
          <WrapperForm wrapperForm={wrapperForm} />
        </Container>
      </Form>
    );
  }
}

export default Account;  

WrapperForm.js

const WrapperForm = (props) => {
  return (
    props.wrapperForm.map((val, idx)=> {
      return (
        <Formik 
          key={idx}
          initialValues={{
            email: props.wrapperForm[idx].email || '',
            password: props.wrapperForm[idx].password || '',
            firstName: props.wrapperForm[idx].firstName || '',
            lastName: props.wrapperForm[idx].lastName || '',
            zipCode: props.wrapperForm[idx].zipCode ||  ''
          }}
        >
          {({ values }) => (
            <Row style={{ marginBottom: "2em" }}>
              <Card>
                <CardHeader>Register</CardHeader>
                <CardBody>
                  <Temp index={idx} />
                </CardBody>
              </Card>
            </Row>
          )}
        </Formik>  
      )
    })
  )
}

Temp.js

const Temp = ({ index }) => {
  let passwordId = 'password-'+ index;
  let firstNameId = 'firstName-'+ index;
  let lastNameId = 'lastName-'+ index;
  let zipCodeId = 'zipCode-'+ index;

  return (
    <Card body outline color="primary">
      <CardTitle>Create Profile</CardTitle>
      <Row form>
        <Col md={6}>
          <Field
            className="email"
            component={customInputForm}
            data-id={index}
            id="email"
            label="Email"
            name="email"
            placeholder="Email"
            type="email"
          />
        </Col>
      </Row>
    </Card>
  )
}
Greg K
  • 10,770
  • 10
  • 45
  • 62
ppb
  • 2,299
  • 4
  • 43
  • 75

3 Answers3

27

I found one solution, maybe it will help someone. You need to create dynamic initialValues for formik as:

let passwordId = 'password-'+ idx ;
let firstNameId = 'firstName-'+ idx;
let lastNameId = 'lastName-'+ idx;
let zipCodeId = 'zipCode-'+ idx;

return (
  <Formik 
      key={idx}
      initialValues={{
          email: props.wrapperForm[idx].email || '',
          [passwordId]: props.wrapperForm[idx].password || '',
          [firstNameId]: props.wrapperForm[idx].firstName || '',
          [lastNameId]: props.wrapperForm[idx].lastName || '',
          [zipCodeId]: props.wrapperForm[idx].zipCode ||  ''
      }}
  >
)
Abraham
  • 8,525
  • 5
  • 47
  • 53
ppb
  • 2,299
  • 4
  • 43
  • 75
5

Reading through all the above comments was really helpful especially in understanding the basic difference between uncontrolled and controlled component in form element within react. However,I got the same error after adding InitialValues as a property to Formik. This opened my mind to the fact that the error occured whenever react view a form input as uncontrolled (controlled within the DOM) combined with state changing function within react component. In fact,I was getting the error because the variable names initialized in my react useState hook are different from the name attribute on my form which I was using as the key to my form inputs. If you get the same error after adding InitialValues property on Formik,you should make sure your state variables are the same with the name attributes on each form input.

Jaylukmann
  • 99
  • 1
  • 3
1

I had a field on my form but no corresponding initial value for it. Once I added the field to initial values (I used a static value, didn't have to be a prop) this error message disappeared.

I notice ppb's answer changes the field names in initialValues from the question, perhaps that made them match?

I presume the component is controlled when an initial value is specified and uncontrolled otherwise.

Greg K
  • 10,770
  • 10
  • 45
  • 62