skip to Main Content

While developing, I extracted part of the content from the parent component into a child component, which is naturally more complex than the code in the example. When I try to enter text in the input box, it loses focus after each input. So I have written similar code to illustrate the issue. Could you please help me resolve this?

import { useState } from 'react';

function App () {
  const [text, setText] = useState('');
  const handleChange = (event) => {
    setText(event.target.value);
  };
  const Input = () => (<input value={text} onChange={handleChange} />)
  return (
    <div className="App">
      <Input />
    </div>
  );
}

export default App;

3

Answers


  1. Such a new way to write I’ve never thought of it before.

    It’s definitely because rerendered, but how it worked maybe need to read react source code.

    Maybe you could try the following code?

    function App() {
      const [text, setText] = useState("");
      const handleChange = (event) => {
        setText(event.target.value);
      };
      const Input = useCallback(
        ({ t, onChange }) => <input value={t} onChange={onChange} />,
        []
      );
    
      return (
        <div className="App">
          <Input t={text} onChange={handleChange} />
        </div>
      );
    }
    
    Login or Signup to reply.
  2. What you did is a declaration of a component within a component:

    const Input = () => (<input value={text} onChange={handleChange} />)
    

    Jack Herrington talks about it in his video "3 React Mistakes, 1 App Killer"

    More in depth explanation: the reason is the mechanism of reconciliation. React compares current shape of Virtual DOM to previous shape. Among other things, the identity of each element is compared, i. e. the reference to the function which creates the element. You create a new reference to Input on each render of App and this is why Input is dismounted and remounted on each text change. I don’t understand why you did that, just do this:

    function App () {
      const [text, setText] = useState('');
      const handleChange = (event) => {
        setText(event.target.value);
      };
      return (
        <div className="App">
          <input value={text} onChange={handleChange}/>
        </div>
      );
    }
    
    Login or Signup to reply.
  3. Move the creation of your Input component outside of the App component (or into a separate file and import it), and pass down the relevant props. Currently the component is being recreated on each new render when the state changes.

    const { useState } = React;
    
    function Input({ text, handleChange }) {
      return <input value={text} onChange={handleChange} />
    }
    
    function App() {
    
      const [text, setText] = useState('');
    
      const handleChange = (event) => {
        setText(event.target.value);
      };
    
      return (
        <div className="App">
          <Input text={text} handleChange={handleChange} />
        </div>
      );
    
    }
    
    const node = document.getElementById('root');
    const root = ReactDOM.createRoot(node);
    root.render(<App />);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search