React / input losing focus 해결방법

Simune·2023년 4월 26일

TIL

목록 보기
1/4

사용자의 피드백을 받아서 에러를 고치는 와중에
글자를 적을 때마다 input에서 포커싱이 나가는 에러가 발생했다.

아래는 내가 사용한 코드와 비슷하게 작성된 코드이다.

{data.map((item) => {
  		...
        <input
          className={styles.data}
          name="data"
          id={item.product.id}
          onChange={() => changeHandler()}
          />
        ...
	}
}

처음에는 단순한 에러라고 생각하고 id를 바꾸고, change event 함수를 바꾸고, map을 바꾸고.. 등등 여러가지를 해봤지만 별 소득이 없어 결국 구글링을 하게 되었다.

이 에러가 발생하는 이유는 re-rendering 때문이었다.
stackover 에 따르면, state가 변경 될 때 리액트는 구성요소를 재정의하여 새로운 요소를 만들게 된다고 한다. 따라서 값이 변경되지마자 요소가 없어지기 때문에 focus도 같이 remove 되고, state가 변경되지 않으면 요소도 변경되지 않게 된다.

stackover 등 여러곳에서 에러 해결방법이 나와있어 차례대로 해보았다.

  1. 분리한 컴포넌트 다시 되돌리기 (분리된 컴포넌트가 없었다)
  2. key 추가하기 (실패)
  3. styled-components 사용하기 (실패)
  4. autoFocus (실패)

autoFocus는 성공한 듯 보였지만, 인풋이 여러개라면 이상한 현상이 발생한다.
포커싱한 어떤 인풋에 key event를 주면 갑자기 가장 마지막 인풋으로 포커싱이 이동한다. (이건 왜인지 모르겠다.)
결국 stackover에서 찾은 모든 해결방법이 통하지 않아 고민하던 와중에 useRef()를 사용해서change event 없이 핸들링하는 방법을 적용해보기로 하였다.

하나의 인풋이 있을때의 useRef는 다음과 같이 사용하면 되지만,

const Component = () => {
  const inputRef = useRef<HTMLInputElement>()
  
  const onClick = () => {
    console.log(inputRef.current.value)
  }
  
  return (
    <input ref={inputRef} />
}

내가 사용하려는 것은 여러개의 인풋에 대한 ref이었고, input value에 id를 함께 ref로 보내야했다.
다음은 그 해결 순서이다.

  1. useRef를 불러온다.
  2. inputRef의 수를 지정한다. (내 코드에서는 products가 변경 가능한 데이터였기 때문에, useEffect의 depenencies에도 추가하였다.)
useEffect(() => {
  inputRef.current = inputRef.current.slice(0, products.length);
}, [products]);
  1. index를 가져온다. (map에서는 item과 index를 둘 다 가져올 수 있다.)
  2. input에 ref을 추가하고 데이터를 설정한다. (i번째 input에 작성된 데이터는 i번째 inputRef에 저장된다는 의미다.)
ref={el => inputRef.current[i] = el}

다른 데이터도 함께 보내고 싶다면 inputRef.current[i] = [el, product.id] 이런 식으로 추가하였다.

  1. submit 할때 ref의 데이터를 전부 불러온다.
for (let i = 0; i < orderProducts.length; i++) {
	const value = inputRef.current[i];
}

나는 다른 데이터와 함께 array 형식으로 보내주었기 때문에 첫번째 값을 inputRef.current[i][0].value로, 두번째 값을 inputRef.current[i][1]로 가져와 원래의 데이터에 추가해주었다.


끝!








참고 자료

profile
👩🏻‍💻🌱

0개의 댓글