form icon indicating copy to clipboard operation
form copied to clipboard

Uncontrolled to controlled input

Open davidohlin opened this issue 5 years ago • 4 comments

Hi!

We're using react-form and it's great, but I have a question about a warning that keeps popping.

When not defining defaultValues I get a warning from react saying that an input was changed from uncontrolled to controlled:

Warning: A component is changing an uncontrolled input of type undefined 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. More info: https://fb.me/react-controlled-components

So I've been setting defaultValues like this, which gets rid of the warning:

const { Form } = useForm({
  defaultValues: React.useMemo(
    () => ({
      email: '',
      password: '',
    }), 
  []),
  onSubmit: async values => {
    handleSubmit(values)
  },
})

Now I have a use case where I need to create inputs dynamically, and while I can compute the values I feel like the form should be usable without defining defaultValues.

This warning is also appears in the basic example from the docs: https://codesandbox.io/s/react-form-demo-wrybd

I guess this happens when react-forms input initializes on an input-field and makes it a controlled one, but I havent been able to wrap my head around it. I would love to hear your thoughts on this!

davidohlin avatar Jan 08 '20 10:01 davidohlin

I'm having the same issue :(

rgbskills avatar Jan 15 '20 12:01 rgbskills

@davidohlin you can define the defaultProps to your component to get rid of this error:

import React from 'react';
import PropTypes from 'prop-types';

export const TextInput = props => <input type="text" {...props} />;

TextInput.defaultProps = {
  value: ''
};

TextInput.propTypes = {
  value: PropTypes.string
};

billwatson017 avatar Jan 15 '20 22:01 billwatson017

@billwatson017 Cool, I'll try that. I tested it quickly on the basic example from the docs and it seems to work.

davidohlin avatar Jan 17 '20 11:01 davidohlin

@tannerlinsley do you think you can change the default behavior of a field value as controlled? Setting the defaultProps or using the defaultValue prop seems like a workaround.

import React from "react";
import ReactDOM from "react-dom";

import { useForm, useField, splitFormProps } from "react-form";

const InputField = React.forwardRef((props, ref) => {
  const [field, fieldOptions, rest] = splitFormProps(props);
  const {
    meta: { error, isTouched, isValidating, message },
    getInputProps
  } = useField(field, fieldOptions);

  return (
    <>
      <input {...getInputProps({ ref, ...rest })} />
    </>
  );
});

function App() {
  const {
    Form,
    meta: { isSubmitting, isSubmitted, canSubmit, error }
  } = useForm({
    debugForm: true
  });

  return (
    <Form>
      <div>
        <label>
          Name: <InputField field="name" />
        </label>
      </div>
    </Form>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

billwatson017 avatar Jan 24 '20 21:01 billwatson017