Home > Mobile >  React keep focus on re-rendering input
React keep focus on re-rendering input

Time:06-26

I am building an e-commerce web app, and have run into a problem making an array of inputs. Inside DescHTML I am trying to handle onChange event, but on each update the focus on the element is lost, making it very annoying to type. Does anyone have any solution or different aproach to this whole problem? Thanks in advance.

import {useState} from 'react'

export default function UploadForm() {
  const [name, setName] = useState('')
  const [category, setCategory] = useState('')
  const [film, setFilm] = useState('')
  const [price, setPrice] = useState('')
  
  const [descArr, setDescArr] = useState([''])
  function DescHTML() {
    return (
    <div>
      { descArr.map((item, i) => 
        <input type="text" placeholder="TEST" key={i} value={item} onChange={(e) => {
          e.preventDefault()
          const newArr = [...descArr]
          newArr[i] = e.target.value
          setDescArr(newArr)
        } } /> )}
    </div>
    )
  }

  console.log(descArr)
  

  return (
    <div>
        <form method="POST" action="http://localhost:3500/api/upload" encType='multipart/form-data'>
            <input type="file" name="image" />
            <input type="text" value={name} name="name" onChange={(e) => setName(e.target.value)} placeholder="Product name" />
            <input type="text" value={category} name="category" onChange={(e) => setCategory(e.target.value)} placeholder="Category" />
            <input type="text" value={film} name="film" onChange={(e) => setFilm(e.target.value)} placeholder="Film" />
            <input type="text" value={price} name="price" onChange={(e) => setPrice(e.target.value)} placeholder="Price" />

            <DescHTML />

            <hr />
            {/*<input type="submit" value="Submit" />*/}
        </form>

        <button onClick={() => setDescArr([...descArr, ''])}> </button>
    </div>
  )
}

CodePudding user response:

Move your descArr and button inside DescHTML check below code you can check more info here.

 function DescHTML() {
    const [descArr, setDescArr] = useState([""]);
    return (
      <div>
        {descArr.map((item, i) => (
          <input
            key={i}
            type="text"
            placeholder="TEST"
            value={item}
            onChange={(e) => {
              e.preventDefault();
              const newArr = [...descArr];
              newArr[i] = e.target.value;
              setDescArr(newArr);
            }}
          />
        ))}
        <br />
        <button onClick={() => setDescArr([...descArr, ""])}> </button>
      </div>
    );
  }

CodePudding user response:

First of all - move DescHTML out of UploadForm:

function DescHTML({descArr, setDescArr}) {
    return (
        <div>
            {descArr.map((item, i) =>
                <input type="text" placeholder="TEST" key={i} value={item} onChange={(e) => {
                    e.preventDefault()
                    const newArr = [...descArr]
                    newArr[i] = e.target.value
                    setDescArr(newArr)
                }}/>)}
        </div>
    )
}

and use it in <UploadForm> like this

<DescHTML descArr={descArr} setDescArr={setDescArr}/>

The other problem is the button which steals the focus on click. Adding onm ouseDown handler will fix this.

<button onm ouseDown={(e) => e.preventDefault()} onClick={() => setDescArr([...descArr, ''])}> </button>
  • Related