js

[React] state가 너무 자주 빠르게 바뀌면?

개발하는 가오나시 2022. 6. 25. 01:48

회사에서 페이지 에디터의 신규 기능을 추가해 달라는 요청이 와서 작업에 들어갔다.

 

간단히 설명하면 우측 에디터에서 값을 입력하면 가운데에 뷰 페이지에 해당 값이 반영되서 보이는 식이다.

 

근데 예를 들어 input 폼에다가 옵션을 넣어준다 생각해보자. placeholder옵션을 주기 위해서 에디터쪽에서 입력을 하면, 가운데 뷰 페이지에 반영을 해야하니 onChange 이벤트를 걸어줬다.

const onChange = (e:React.ChangeEvent<HTMLInputElement>)=>{
	const value = e.target.value;
    
    setState({[target]:value})
}

근데 이러면 어떻게 되냐. 타자를 칠 때마다 상태가 업데이트 된다.

 

물론 이거가지고 막 느려지거나 하지는 않겠지만, 이런 경우가 점점 많아 진다면? input의 key가 되는 name이나 initialValue를 입력해주는 기능도 들어가야하는데, 키보드를 칠 때마다 상태가 업데이트된다면, 진짜 쓸데없는 화면 업데이트가 파바바박 일어날 것이고, 아무리 react에서 setState로 state를 업데이트 할 때, 비동기 적으로 한번에 업데이트를 진행한다 한들, 값을 입력하는 것 부터 버벅이게 될 수 있다.

 

그리고 실제로 그랬다.

 

그래서 생각했다. 어차피 원하는 결과를 타이핑을 끝낸 최종 결과물만 제대로 보이면 되는건데 이걸 어떻게 한번에 업데이트를 칠까.

 

고민한 결과 업데이트 함수를 호출할 때, 약간의 텀을 줘서 일정 시간이 지나기전에 또 업데이트가 되려고 한다면, 기존 상태를 버리고 새로 들어오는 값으로 업데이트를 하는 방식으로 해결했다.

 

  const dataUpdateQuee = useRef<number | undefined>();

  const onChangeFormItem = useCallback(
    ({ newValue, target, targetIdx }) => {
      const items = value.items || [];
      const newItems = items.map((data, idx) =>
        idx !== targetIdx ? data : { ...data, [target]: newValue }
      );

      if (dataUpdateQuee.current) {
        clearTimeout(dataUpdateQuee.current);
      }

      dataUpdateQuee.current = setTimeout(() => {
        onChange({ items: newItems });
        dataUpdateQuee.current = undefined;
      }, 200);
    },
    [value.items, onChange]
  );

값이 업데이트가 되어도 랜더링이 되지않는 useRef를 이용하여 상태를 업데이트해주는 인터벌 함수를 저장해주자.

 

일단 change이벤트가 발생하면, 새로들어온 값으로 상태를 다시 만들어준다. 이때, 기존에 업데이트 대기중인 인터벌이 있다면 해당 이벤트를 clearTimeout으로 멈추고 새로운 인터벌을 타이머Ref에 넣어준다.

 

이러면 우리가 타자를 타다다다다 쳐도 200ms안에 친다면, 칠 떄마다 업데이트 되는것이 아니라 변경될 값을 잘 쌓아 두다가 200ms가 지나면 업데이트가 될것이다.

 

 

 

내가 만드는 서비스에서 버벅인다니. 있을 수 없는 일이고말고