Demo, all content is generated
Question

Input loses focus after every letter I type

Solved · 2641 views · asked by quietmaya · edited

I have a search field in a list page. Type one letter → the field loses focus, I have to click again for the next letter. v0 generated the component, I added a few things with Cursor.

export default function ProductList({ products }) {
  const [query, setQuery] = useState("");

  function SearchBox() {
    return <input value={query} onChange={(e) => setQuery(e.target.value)} />;
  }

  return (
    <div>
      <SearchBox />
      {products.filter((p) => p.name.includes(query)).map(...)}
    </div>
  );
}
What I’ve tried

Added autoFocus (then it jumps to the end weirdly), asked v0 twice, it moved the useState around.

Comment
Ha, I can see it from here. Answer coming. aiko_n · edited

3 answers

Marked as helpful by the asker
aiko_n · edited

SearchBox is defined inside ProductList. Every render (so every keystroke) creates a brand-new SearchBox function, and React sees it as a different component type. It throws away the old input and mounts a new one, which has no focus.

Move it out, pass what it needs:

function SearchBox({ value, onChange }) {
  return <input value={value} onChange={(e) => onChange(e.target.value)} />;
}

export default function ProductList({ products }) {
  const [query, setQuery] = useState("");
  return (
    <div>
      <SearchBox value={query} onChange={setQuery} />
      ...

Or just inline the <input> there, it's one line.

Rule: never declare a component inside another component.

Comment
wow. moved it out and it works. I would never have figured that out. quietmaya · edited
Had the exact same bug with a modal, thank you rosa_m · edited
Linking this one to people regularly. sarah_k_dev · edited
kofi_mensah · edited

Same symptom, other cause to check if you ever see it again: a changing key. Something like key={Math.random()} or key={query} on the input or a parent also remounts it every keystroke.

Comment
chidi_eze · edited

ESLint can catch this for you: react/no-unstable-nested-components from eslint-plugin-react flags components declared inside other components.

Comment