Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Generate input/label element in React child component conditionally but got a 'component is changing an uncontrolled input to be controlled.' warning

As a React beginner, I want to build a simple to-do list app.
There is a list of some tasks, and list items are generated by list.map().
And If <label> is double-clicked, turn that label into <input type="text"> so the user can modify the task.
So I tried using some states in the Parent component and passed props to the child component like this.

export default function App() {

  let list = [
    {
      "id": "id-1"
      "title": "get some sleep"
    },
    {
      "id": "id-2"
      "title": "check the mailbox"
    },
    {
      "id": "id-3"
      "title": "ask question to stackoverflow"
    }
  ]

  const [editTargetTaskId, setEditTargetTaskID] = useState<string>(``);
  const [editMode, setEditMode] = useState<boolean>(false);

  const toggleEditMode = (editMode: boolean) =>
    editMode ? setEditMode(false) : setEditMode(true);

  // When double click the label, change states
  const triggerEdit = (e: React.MouseEvent<HTMLLabelElement>) => {
    setEditTargetTaskID(e.currentTarget.parentElement?.id || ``);
    toggleEditMode(false);
  };

  const editTask = (
    newInput: string,
    list: Task[],
    editTaskId: string,
    editMode: boolean
  ) => {
    setList(
      list.map((task: Task) => {
        if (task.id === editTaskId) {
          return { ...task, title: newInput };
        } else return task;
      })
    );
    toggleEditMode(editMode);
  };

  return (
      <ul>
        {list.map((task: Task) => (
          <li key={task.id} id={task.id}>
            <TaskListItem
              task={task}
              list={list}
              isEdit={editMode}
              triggerEdit={triggerEdit}
              editTaskId={editTargetTaskId}
              editTask={editTask}
            />
          </li>
        ))}
      </ul>
  )

And this is the child component list item.

interface ITaskListItemProps {
  task: Task;
  isEdit: boolean;
  editTaskId: string;
  list: Task[];
  triggerEdit: (e: React.MouseEvent<HTMLLabelElement>) => void;
  editTask: (
    newInput: string,
    list: Task[],
    editTaskId: string,
    editMode: boolean
  ) => void;
}

export default function TaskListItem({
  isEdit,
  editTaskId,
  task,
  list,
  triggerEdit,
  editTask,
}: ITaskListItemProps) {
  const [updateInput, setUpdateInput] = useState<string>(task.title);
  const handleUpdateInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    setUpdateInput(e.target.value);
  };

  if (isEdit && editTaskId === task.id) {
    return (
      <>
        <input type="text" value={updateInput} onChange={handleUpdateInput} />
        <button
          type="button"
          onClick={() => editTask(updateInput, list, editTaskId, isEdit)}
        >
          update
        </button>
      </>
    );
  } else {
    return (
      <>
        <input type="checkbox" />
        <label onDoubleClick={triggerEdit}>{updateInput}</label>
      </>
    );
  }
}

It seems to be working well at the first time, but I’ve got a warning message on the console ‘A component is changing an uncontrolled input to be controlled.’.
How can I handle this warning? Should I use some of the other hooks like useEffect()?
Thanks in advance!

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

If you notice the in your if-else statement, input text and input checkbox, the input text is controlled by a local state, while input checkbox is not.

This is likely the cause of the error.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading