React Hook 비동기

lim1313·2021년 8월 13일
0

ERROR 리뷰

목록 보기
2/8

Twittler 과제 중 만난 에러

1. filtering 기능 구현

동작 안됨

if문 안에서 return을 써주거나 else if로 조건을 나눠줘야 했었다.

<script>
// filter 기능 구현

let [selectUser, setSelectUser] = useState(dummyTweets);
let [dummy, setDummy] = useState(dummyTweets);

  const handleChangeUser = (e) => {
    if (e.target.value === "all user") {
      setSelectUser(dummyTweets);
    } 
      setSelectUser(dummyTweets.filter((v) => v.username === e.target.value));
  };

</script>

동작됨!!

<script>
// filter 기능 구현

//방법1
 const handleChangeUser = (e) => {
    setSelectUser(
      e.target.value !== 'all user'
        ? dummyTweets.filter((v) => v.username === e.target.value)
        : dummyTweets
    );
  };


// 방법2
if (e.target.value === 'all user') {
      return setSelectUser(dummy);
    }
    return setSelectUser(dummy.filter((v) => v.username === e.target.value));

</script>

해당 에러에 대해 찾던 도중, 처음에는 hook를 if문 안에 넣어주면 안된다는 글을 보게 되었는데, 이를 setState는 if문 안에 넣어주면 안된다라고 잘못 이해하게 되었다. 그 부분때문에 꽤 많은 시간을 소모했다.

오늘 다시 블로그를 쓰면서 처음 작성한 에러 코드를 보니, setState가 아닌 useEffect나 useState를 if문안에서 쓰면 안된다는 것이었다.
react 문서를 찾아보니 Hook은 반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하지 말라고 나와있다.
이 규칙을 따라야 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출된다고 한다.

https://ko.reactjs.org/docs/hooks-rules.html#explanation

참고)
React는 모든 Hook들이 확실히, 매번 같은 순서로, 매번 같은 개수로 실행되기를 원합니다. 따라서 함수 안이나 조건문 안에서는 훅을 선언할 수 없는 것이죠. 매번 같은 개수는 무엇을 말하는 걸까요? 반복문 내부에서 실행되면 안 된다는 뜻입니다. React에서는 map을 사용하는 경우가 많은데 이 때 map안에 Hooks을 넣으면 안 됩니다.


2. delete 기능 구현

동작 안됨

-> dummy state를 가져올 때 splice가 적용되기 전의 dummy 값을 가져오기 때문에 제대로 delete된 상태를 화면에 출력하지 않은 것 같다.

<script>

const deleteMsg = (v) => {
  dummy.splice(dummy.indexOf(v), 1);
  setDummy(dummy);
  setSelectUser(dummy);
};

</script>

동작됨

-> 그래서 dummy 값이 아닌, 삭제된 후의 dummy값을 value 변수에 할당하여, setDummy 인자로 전달해 주었다.

<script>

const deleteMsg = (v) => {
    let value = dummy.filter((a) => a.id !== v.id);
    setDummy(value);
    setSelectUser(value);
  };

</script>

setState 비동기

setState는 비동기로 동작한다.
setState를 한번에 처리힌다.

아래의 코드를 보면 upNumber함수에 setState가 두 개가 있지만, setState는 비동기이기 때문에 한번에 처리되어 랜더링은 1번만 일어난다.

비동기 참고)
만약 state 변경이 Sync 동기적으로 작동한다면 state의 변경이 한꺼번에 여러번 많이 발생하게 될경우 그 만큼 많은 렌더링이 많이 발생하게 되어 유저는 갑작스런 멈춤을 경험하게 될 것입니다. 이를 방지하기 위해 state의 변경사항을 즉시 반영하지 않고 변경사항을 Queue에 넣었다가 일괄 적용 시킵니다.

<script>

import React, { useState } from 'react';
import './App.css';

function App() {
  const [update, setUpdate] = useState(0);
  const [down, setDown] = useState(0);

  console.log('render', update, down);

  const upNumber = () => {
    setUpdate((prevState) => prevState + 1);
    setUpdate((prevState) => prevState + 1);
    // 2씩 증가
   // 최신값으로 업데이트!
  };

  const downNum = () => {
    setDown(down - 1);
    setDown(down - 1);
    // 1씩 감소
    //setDown의 연이은 호출은 같은 주기 내의 바로 직전 호출 결과를 덮어쓰고, 따라서 수량값이 한번만 감소됨.
  };

  return (
    <>
      <div>{update}</div>
      <div>{down}</div>
      <button onClick={upNumber}>up</button>
      <button onClick={downNum}>down</button>
    </>
  );
}

export default App;

</script>

관련 react 문서 (setState())
https://ko.reactjs.org/docs/react-component.html#setstate


깨달음

에러를 찾고 해결방법을 찾는 과정에서 에러코드와 수정코드, 그리고 자신이 이해한 바를 글로 남겨두는 것이 중요하다는 것을 이번에 느끼게 되었다.
가장 중요한 것은 이를 다시 구현하고 자신이 이해한 바가 맞는 것인지 아니면 오늘과 같이 착각한 부분은 없는지 확인하는 과정이다.

에러의 해결방법을 찾고 좋아하지만 말고, 실수한 코드를 좀 더 세밀하게 들여다 보는 습관을 가지자!

profile
start coding

0개의 댓글