0

In this example below, I want to reset the input field back to an empty string after clicking submit: https://codesandbox.io/s/todo-app-object-vk99c

Form.js:

class Form extends Component {
  state = {
    todo: { name: "" }
    // inputValue: ""
  };

  onChange = (e) => {
    const newTodo = {
      id: Math.random() * 10000,
      name: e.target.value,
      completed: false
    };

    this.setState({
      todo: newTodo
    });
  };

  onSubmit = async (e) => {
    e.preventDefault();
    this.props.addTodo(this.state.todo);
    console.log(this.state.todo, "this.state.todo 1");
    await this.setState({
      todo: {}
    });
    console.log(this.state.todo, "this.state.todo 2");
  };

  render() {
    return (
      <form className="Form">
        <input
          type="text"
          className="input"
          onChange={this.onChange}
          value={this.state.todo.name}
        />
        <button className="submit" onClick={this.onSubmit}>
          Submit
        </button>
        {this.state.todo.name}
      </form>
    );
  }
}

export default Form;

App.js:

 addTodo = (newTodo) => {
    const newState = [...this.state.todos, newTodo];
    this.setState({
      todos: newState
    });
  };

My questions are:

  1. I want to update the name string to an empty string, and it seems like it works if it's not part of the input field. Why is this happening? Before I click submit: https://i.sstatic.net/0kuEo.jpg , After I click submit: https://i.sstatic.net/TaI13.jpg (Notice how the text next to the submit button is reseted to an empty string, so why does React update the state in 1 place but not the other?)

  2. I got the following warning:

Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components
    at input
    at form
    at Form (https://vk99c.csb.app/src/Components/Form/Form.js:50:34)
    at div
    at App (https://vk99c.csb.app/src/App.js:51:34)

Which I think is rather vague. I know the Form (which is a controlled input in React) is the problem, but don't understand what the warning is telling me, and how to fix it.

Update: I believe this code has something to do with it:

onSubmit = async (e) => {
    e.preventDefault();
    this.props.addTodo(this.state.todo);
    console.log(this.state.todo, "this.state.todo 1");
    await this.setState({
      todo: {
        name: {}
      }
    });
    console.log(this.state.todo, "this.state.todo 2");
  };

When I changed {} to "", it works, and the warning is gone, but still, I don't understand why it will work at one place but not the other, and what the warning was saying.

EDIT: I got suggested this answer React - changing an uncontrolled input , but it is not my situation, as my initial state wasn't an empty object in Form.js

todo: { name: "" }
7
  • 1
    In your codesanbox snippet you do this.setState({todo: {}}), since this doesn't have a name key, using this.state.todo.name as a value doesn't correspond to a state value, as the name key does not exist on the todo object. Commented Mar 14, 2021 at 2:44
  • I did notice that as well. However, why was it that the string next to the submit button still being updated (reset to empty string) whereas the string in the input field was not, because they were controlled by the same onSubmit function? Commented Mar 14, 2021 at 2:46
  • 1
    That's because your onSubmit will set the state to {todo: {}}, as a result this.state.todo.name will be undefined. React doesn't display undefined values, so it gets hidden in the output. Since your value for the input field is now not set to a state value you'll get the error about it being uncontrolled. You can see this by checking for undefined and manually showing a string value: {this.state.todo.name === undefined ? "undefined" : this.state.todo.name}. this will show "undefined" when this.state.todo.name is undefined Commented Mar 14, 2021 at 2:50
  • 1
    Yes, that's right, it's because it's undefined that it's not being displayed, not because it's an empty string. The value of the input box does not change though, since setting the value to undefined just makes the input box "uncontrolled", it doesn't change the value within the textbox/input - more here Commented Mar 14, 2021 at 3:00
  • 1
    The way I think about it is if an input is controlled, then there is some state that is driving the value of that input. When the value is undefined, then there is no state driving its value anymore, so it's not being controlled by your applications state (ie: it's uncontrolled). In practice, this could lead to inconsistency between your react state and what's being entered into the input textbox (ie the DOM) - more info in the first paragraph of this article. Commented Mar 14, 2021 at 3:28

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.