Home > OS >  Why is my input field losing focus when typing a character?
Why is my input field losing focus when typing a character?

Time:08-25

I have a form that have several input fields and for some reason my component y re-rendering everytime y change the value of my input field which produces to the input to lose focus.

ContactForm.js:

const ContactForm = () => {

  const [values, setValues ] = useState({
    name: '',
    lastname: '',
    email: '',
    confirmEmail: '',
    message: ''
  });

const inputs = [
    {
      id: Math.random(),
      name: 'name',
      type: 'text',
      placeholder: 'Name'
    },
    {
      id: Math.random(),
      name: 'lastname',
      type: 'text',
      placeholder: 'Last Name'
    },
    {
      id: Math.random(),
      name: 'email',
      type: 'email',
      placeholder: 'Email'
    },
    {
      id: Math.random(),
      name: 'confirmEmail',
      type: 'email',
      placeholder: 'Confirm Email'
    },
    {
      id: Math.random(),
      name: 'message',
      type: 'text',
      placeholder: 'Message'
    }
  ]

  const handleSubmit = (e) => {
    e.preventDefault();
    
  }

MY child component, FormInput.js:

import React from 'react'
import './FormInput.css';
/* import { Input } from '../atoms/Input'; */

const FormInput = (props) => {

  const { id, onChange, ...inputProps } = props;

  return (
    <div className='formInput'>
        {/* <label htmlFor="">Username</label> */}
        {/* <Input {...inputProps} onChange={onChange}/> */}
        <input {...inputProps} onChange={onChange} />
    </div>
  )
}

export default FormInput





    const onChange = (e) => {
        setValues({...values, [e.target.name]: e.target.value}); 
      }
    
    
    
    
      console.log(values);
      
    
      return (
        <form className='contactForm' onSubmit={handleSubmit}>
          {inputs.map((input) => (
            <FormInput 
            key={input.id} 
            {...input} 
            value={values[input.name]} 
            onChange={onChange}
            />
          ))}
          <SubmitBtn/>
          
          
        </form>
      )
    }

So is there a solution for this, so that my input field doesn´t lose focus after re-rendering? Or should i prevent re-rendering?

CodePudding user response:

you have 3 options here.

  1. move the input array outside of the component so that it is always the same on every iteration. But if you are fetching this from the server, that is not possible.

  2. you can use a useMemo hook on the input array and make sure to pass an empty array as a dependency array.

  3. remove the Math.random function and maybe use a unique id from the server or for the time being you can use the array index (even though it is not advisable).

I have created a small POC. if you remove the useMemo, the input(s) will lose their focus on every re-render.

Following is the code:

import * as React from 'react';
import './style.css';

export default function App() {
  const inputs = React.useMemo(
    () => [
      {
        id: Math.random(),
        name: 'name',
        type: 'text',
        placeholder: 'Name',
      },
      {
        id: Math.random(),
        name: 'lastname',
        type: 'text',
        placeholder: 'Last Name',
      },
      {
        id: Math.random(),
        name: 'email',
        type: 'email',
        placeholder: 'Email',
      },
      {
        id: Math.random(),
        name: 'confirmEmail',
        type: 'email',
        placeholder: 'Confirm Email',
      },
      {
        id: Math.random(),
        name: 'message',
        type: 'text',
        placeholder: 'Message',
      },
    ],
    []
  );

  const [state, setState] = React.useState({
    name: '',
    email: '',
    message: '',
    confirmEmail: '',
    lastname: '',
  });

  const handleChange = (e: any) => {
    const value = (e.target as HTMLInputElement).value;
    const name = (e.target as HTMLInputElement).name;
    setState({
      ...state,
      [name]: value,
    });
  };

  const handleSubmit = () => {
    console.log('state', state);
  };

  return (
    <div>
      {inputs.map((item) => (
        <div key={item.id}>
          <label>{item.name}:&nbsp;</label>
          <input
            name={item.name}
            onChange={handleChange}
            placeholder={item.placeholder}
          />
        </div>
      ))}
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
}

CodePudding user response:

It's probably because you are calling Math.random in the body of the ContactForm component. You should never call Math.random() during rendering. In your case, you can probably move the const inputs to outside the component.

  • Related