FrontEngineer JungBam

리액트 훅과 렌더링 본문

리액트

리액트 훅과 렌더링

정밤톨 2022. 11. 26. 07:40
항해 1주차 과제를 마치고 소름이 돋았다.. 
리액트를 지난 두달간 했음에도 렌더링을 이제서야 깨닫다니..
스냅샷에 대한 이해가 전혀 없었다. state를 스냅샷이라고 설명이 많았음에도 그 스냅샷을 그냥 그 순간을 포착하는 캡처 기능처럼 순간의 데이터를 저장하고 있다라는 개념만 갖고 있었다라나..
이 state에 의한 렌더링의 이해가 필요하다는 생각에 희열을 느꼈다 진짜로.
그럼에도 useEffect과 의존성 배열은 확실히 이해가 되어있다는 걸 느껴서 다행이다고 생각이 들더라.

내가 작성한 코드

  const [workingArray, setWorkingArray] = useState([])
  const [doArray, setDoArray] = useState([])
  const [doneArray, setDoneArray] = useState([])
...(중략)...
  useEffect(() => {
    setDoArray(workingArray.filter((el) => el.idDone === true))
    setDoneArray(workingArray.filter((el) => el.idDone === false))
  }, [workingArray])

코드리뷰 후 수정된 코드

  const [workingArray, setWorkingArray] = useState([])
 
  const doArray = workingArray.filter((el) => el.idDone === true)
  const doneArray = workingArray.filter((el) => el.idDone === false)

1. 코드를 딱 비교해보면 다른건 둘째치고 불필요한 상태관리가 되고 있다.

★ doArray와 doneArray가 workingArray에서 파생되는데 workingArray를 이미 리액트가 관리중이기 때문에 그로 인해 파생된 doArray와 doneArray는 당연히 workingArray에 의해 관리되고 있는 것이다.

```지금보니까 소름이 또 돋는다..```

2. state에 대한 이해가 완전 부족했다.

```매니저님 曰 : 렌더링에 대한 이해가 전혀 안됐다라고 볼 수 있겠는데요. 다시 공부해야 될 것 같아요.```

(근데 듣고나서 기분이 너무 좋았다. 확실히 틀리게 알고 있었다라는 걸 깨닫게 되어서 너무 감사했다.)

useState에서 setState에 의해 변경된 스냅샷은 리렌더링 과정에서 반영되는 값이다.
즉, 리렌더링 전에 setState로 인해서 값이 변경되었다고 착각하면 안된다. 이게 무슨말이냐면 아래 코드로 보면 바로 이해가 된다.
const [count, setCount] = useState(0)

const clickHandler = ()=>{
  setCount(count+1)
  setCount(count+1)
  setCount(count+1)
  setCount(count+1)
  setCount(count+1)
}
clickHandler로 인해 변경된 값은 +5일까? 정답은 아니다. count라는 값이 저장되어 렌더링된 순간 리렌더링 되기 전까지는 그 값은 변하지 않는다. 즉 저건 0+1+1+1+1+1이 아니라 0+1 => 0+1 => 0+1 => 0+1 => 0+1 이 짓을 하고 있는 것이다.
위와 같은 생각을 구현하는 방법은 마지막에 설명하고 지금 이 state에 대한 이해가 되었다면 다시 내가 작성한 코드를 보자.
const Handler = ()=>{
    setWorkingArray([...workingArray, doc])
    setDoArray(workingArray.filter((el) => el.idDone === true))
    setDoneArray(workingArray.filter((el) => el.idDone === false))
}
이게 완전 처음에 작성한 코드였는데 이상하게 state에 관리되어야 하는 doArray와 doneArray가 변하지 않는 것이다. 내 생각은 이랬다.
```workingArray가 변했고 그 변한 값으로 filter를 통해 doArray와 doneArray를 만들어줬으니 바로 렌더링되겠지?```
근데 렌더링이 되지 않는다? 위의 count에 대한 이해가 되었다면 당연하다.
1. workingArray가 이 다음 렌더링 과정에서 변한 값이 반영되는데 반영되고 다시 Handler 함수가 호출되어야 doArray와 doneArray가 리렌더링 되는건데 일단 다시 호출하기 전까지는 리렌더링 될 일이 없다.
2. workingArray가 setter에 의해 값이 즉각적으로 변한다는 잘못된 setter에 대한 이해가 부른 멍청한 코딩이었다.

```매니저님은 이런 내 생각을 setter로 구현하는 방법도 알려주셨는데 바로 setter함수의 인자로 함수를 주는 방법이다. 코드로 보자.```
const [count, setCount] = useState(0)

const clickHandler = ()=>{
  setCount((prev)=>prev+1)
  setCount((prev)=>prev+1)
  setCount((prev)=>prev+1)
  setCount((prev)=>prev+1)
  setCount((prev)=>prev+1)
}

setter에 함수를 주면 함수 인자로 이전값을 받아 올 수 있다. 아까 생각한 setter로 변경하고 바로 변경하고 변경하고 리렌더링 이런 생각을 구현할 수 있다는 것이다. 아까 봤던 count와는 다르게 이 친구는 +5가 된다. 0+1+1+1+1+1이 되고 리렌더링!

반응형

'리액트' 카테고리의 다른 글

배열 컴포넌트 생성시 key  (0) 2022.11.28
useContext  (1) 2022.11.27
useReducer  (1) 2022.11.24
useEffect를 이용한 debounce, throttle 처리  (0) 2022.11.24
LocalStorage와 useEffect  (0) 2022.11.23
Comments