Reducer & context api & useEffect

Hover·2022년 7월 25일
0

Udemy리액트

목록 보기
18/19

1. useEffect & sideEffect란?

리액트의 메인 기능은 UI를 사용자가 필요할 때(사용자 입력에 반응)렌더링 하는것입니다.

사이드이펙트는 애플리케이션에서 일어나는 위와 다른 모든 것들을 뜻합니다.

예를들어 http request나 browser store(local)에 무언가를 저장하는 것 등이 있습니다.

또한 코드에서 타이머나 간격을 설정할 때도 사용합니다.

useState가 변경 될때마다 해당 컴포넌트 함수는 재실행됩니다.

재실행하면서 작성했던 JSX코드를 확인하고 이전 결과와 비교해 변경된 DOM을 확인합니다.

만약 http request를 컴포넌트 함수에 직접 보내면 useState가 실행될 때마다 request를 다시 보내게 됩니다.

위 방법이 필요할 경우도 있지만, 무한 루프로 빠질 가능성도 있습니다.

이때 사용하는 것이 useEffect hooks입니다.

useEffect(()=>{...},[dependencies]);

useEffect는 위와 같이 선언됩니다.

첫번째 인자는 함수입니다. 모든 컴포넌트 평가 후 실행되어야 하는 함수입니다.

두번째 인자는 의존성으로 구성된 배열입니다. 이 배열이 변경될때마다 첫번째 인자인 함수가 다시 실행됩니다.

따라서 첫번째 함수에 sideEffect함수를 넣고 의존성배열이 변경될 때마다 실행 될 것입니다.

컴포넌트의 렌더링으로 재실행되는 경우는 없습니다.

2.useEffect() 훅 사용하기

useEffect를 사용하기 전에 localstorage에 대해 알아보겠습니다.

  const loginHandler = (email, password) => {
    // We should of course check email and password
    // But it's just a dummy/ demo anyways
    localStorage.setItem('isLoggedIn','1'); <<new
    setIsLoggedIn(true);
  };

login시 실행하는 함수입니다.
email,password의 인자를 받고 로그인하면 useState로 관리되는 isloggedin이 true로 변환됩니다.

여기서 localstorage를 통해 두 개의 키와 밸류값을 설정해주는데

개발자도구를 확인해보면 이런 방식으로 나타납니다.

여기서 새로고침을 하면 리렌더링되면서 컴포넌트 함수가 다시 실행되는데

  const storedUserLoggedInInformation = localStorage.getItem('isLoggedIn');


  if(storedUserLoggedInInformation==='1'){
    setIsLoggedIn(true);
  }

상수를 하나 선언해주고 localstorage를 getitem해줍니다.
여기서 getitem의 props를 isloggedin으로 해주면 해당 상수에는 키-밸류의 값인'1'이 들어갑니다.

위와 같은 방법도 사용되지만, 이 방법에는 무한 루프를 만들 수도 있다는 문제점이 있습니다.

그래서 사용하는것이 useEffect입니다.

  useEffect(()=>{
      const storedUserLoggedInInformation = localStorage.getItem('isLoggedIn');
      if(storedUserLoggedInInformation==='1'){
      setIsLoggedIn(true);
    }
  },[]); 

useEffect는 모든 컴포넌트 내 함수가 실행된 후 제일 마지막으로 실행됩니다.(1회만)
따라서 여기서 모든 함수 실행 후 state가 업데이트 됬을 경우 컴포넌트 함수를 재실행합니다.
해당 함수는 종속성이 없으니 항상 실행됩니다.

3. useEffect의 종속성

Login.js는 이메일에서 @의 포함여부와 패스워드의 글자 길이를 조건으로 하여
로그인 입력창을 setFormIsValid로 결정합니다.

예를들어 formisValid가 false면 login을 하지 못하는 상태가 됩니다.

원래 코드에서는 emailChangeHandler하고 passwordChangeHandler에 state를 넣어 주었습니다.

하지만 이 역시 값이 변경될때마다 state가 변경되어 리렌더링이 됩니다.

이 state를 useEffect를 통해 dependency를 추가하여 실행해보자 합니다.

useEffect(()=>{
    setFormIsValid(
      enteredEmail.includes('@') && enteredPassword.trim().length > 6
      //boolean && boolean
    );
  },[setFormIsValid,enteredEmail,enteredPassword])

setFormIsValid,enteredEmail,enteredPassword 이 세 변수 또는 함수가 실행or변화하면 useEffect내의 함수가 실행됩니다.

dependency배열에 함수의 실행이 아닌 함수의 포인터를 추가합니다.(setFormIsValid)
함수의 실행을 추가하면 함수의 결과값이 의존성에 들어가므로 옳지 않은 결과가 도출될 수도 있습니다.

여기 3개의 의존성의 컴포넌트 렌더링 주기에 변경된 경우만 setFormIsValid를 실행합니다.

무언가에 대한 응답(sideEffect)으로 실행되는 코드에 useEffect는 굉장히 효율적입니다.

4.useEffect에서 cleanup함수 사용하기

사용자 입력 한글자 한글자마다 setFormValid를 실행하면 메모리적으로 낭비가 있을 겁니다.

그러나, 사용자의 입력 완료를 기다렸다가 setFormValid를 실행하는 방법도 있습니다.

그것은 브라우저 내 함수인 timer를 이용하는 것입니다.

setTimeout(()=>{},time)

setTimeout은 타이머가 만료 된 뒤 함수를 실행하는 메소드입니다.

clearTImeout(timerfunction)

clearTimeout은 해당 타이머를 제거해주는 전역 메소드입니다.

useEffect에는 또다른 기능이 있습니다.

useEffect(()=>{
  function()
  return cleanupFunction()
},[dependency]

cleanupFunction은 useEffect에서 return으로 선언할 수 있는 함수입니다.

1.useEffect로 선언한 sideEffect function이 실행될 때 실행(첫 번째 sideEffect실행은 실행x)
2.특정 컴포넌트가 재사용될 때마다 실행

총 두 가지의 경우 cleanupFunction은 실행됩니다.

  useEffect(()=>{
    const identifier = setTimeout(()=>{
      console.log("checking");
      setFormIsValid(
        enteredEmail.includes('@') && enteredPassword.trim().length > 6
        //boolean && boolean
      );
    },500);
    return ()=>{
      console.log('cleanup');
      clearTimeout(identifier);
    }; 
  },[enteredEmail,enteredPassword])

setTimeout에 Valid검사 함수를 넣어주고 500의 시간을 줍니다.
그리고 cleanupFunction에 clearTimeout을 넣어줍니다.

이렇게 되면 sideEffect함수에서 타이머를 설정하기 전에 마지막 타이머를 지웁니다.
사용자가 타이핑을 계속 하면 sideEffect함수가 계속 실행이 되는데 그걸 clearTimeout으로 타이머를 모두 없애고
사용자가 타이핑을 멈춘 뒤 500의 시간 뒤에 sideEffect함수가 실행되는 것입니다.

1.sideEffect함수의 실행, 그러나 500의 시간동안 딜레이
2.그동안 cleanup함수 발생
3.다음 타이핑을 치면 마지막 타이머를 삭제하고 다시 sideEffect함수 실행,500의 시간동안 딜레이
4.타이핑을 멈추면 더이상 sideEffect함수가 실행되지 않으므로 이로인해 다음 cleanup또한 실행이 안되므로 500의 시간 딜레이 후 이전 sideEffect함수 실행

타이핑을 하면 cleanup이 먼저 나오는 이유입니다.

//작성중....

profile
프론트엔드 개발자 지망생입니다

0개의 댓글