Search code examples
reactjstypescript

Input loses focus when the state of the default value gets changed in React


I have an application where I have the Dialog.tsx which generates a pretty neat InputField that looks always the same.

When I try to type into the TextField it types one character and then loses focus because of the setDocumentName, since it changes the documentName value that is used as the defaultValue for the TextField

App.tsx:

import { useState } from "react";
import "./App.css";
import * as React from "react";
import { Dialog } from "./Components/Dialog";

function App() {
  const [documentName, setDocumentName] = useState("");

  return (
    <>
      <Dialog
        id="documentName"
        defaultValue={documentName}
        onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
          setDocumentName(event.target.value);
        }}
      />
    </>
  );
}

export default App;

Dialog.tsx:

import * as React from "react";

export interface DialogProps {
  id: string;
  defaultValue?: string;
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

export const Dialog: React.FC<DialogProps> = ({
  id,
  defaultValue,
  onChange,
}) => {
  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (onChange) {
      onChange(event);
    }
  };

  return (
    <>
      <input
        key={defaultValue + "-input"}
        id={id}
        defaultValue={defaultValue}
        onChange={handleChange}
      />
    </>
  );
};

I've tried several Stack Overflow solutions and also asked ChatGPT but never got one working.

Solution

Instead of using the defaultValue as part of key I give a keyValue to the component and insert it into the property key.


Solution

  • Here are some points I got from your code :
    - Writing on the TextField update documentName (in App.tsx)
    - documentName is provided to TextField as prop defaultValue
    - TextField's root element use defaultValue in its key

    When the key attribute change, React destroy the element from the dom and create a new one. Basically you have a new input which by default is not focused.
    Most of the time, you use key whan you have to manage a list, which is not your case here. Just remove it should probably fix your issue.