useEffect 자세히 이해하기 2- Side Effect와 Clean up function

김명성·2022년 5월 11일
0

REACT

목록 보기
24/32
import React, { useState,useEffect } from 'react';

import Card from '../UI/Card/Card';
import classes from './Login.module.css';
import Button from '../UI/Button/Button';

const Login = (props) => {
  const [enteredEmail, setEnteredEmail] = useState('');
  const [emailIsValid, setEmailIsValid] = useState();
  const [enteredPassword, setEnteredPassword] = useState('');
  const [passwordIsValid, setPasswordIsValid] = useState();
  const [formIsValid, setFormIsValid] = useState(false);

  // useEffect의 본질은 Side Effect의 관리다.
  // side Effect는 보통 http Request이지만,
  // 키 입력을 듣고 입력된 데이터를 저장하는 것도 Side Effect이다. 
  // 그에 대한 응답으로 다른 Action을 실행하는 것도 side Effect이다.
  // 아래 useEffect에 담긴 Action은 이메일/비밀번호 필드에서 입력되는 값을 보고
  // 입력되는 값에 대한 응답으로 해당 폼의 유효성을 검사하고 업데이트 하는 것 또한
  // 사용자가 입력한 데이터에 관련된, UI와 관계 없는 Side Effect이다.
  // 중요한 점은 어떤 Action에 대한 응답으로 실행되는 Action이 있다면
  // 그것이 Side Effect라는 점이다.
  useEffect(()=>{
    // 단축평가로 값을 반환 - 조건에 부합하면 truthyh로 변경.
    // useEffect 바깥으로 setFormIsValid를 꺼내놓는다면 
    // formIsValid가 변경되면서 컴포넌트를 다시 랜더링하고
    // 코드는 컴포넌트가 다시 렌더링 될 때마다 재실행되며 무한 loop에 빠지게 된다.
    const identifier = setTimeout(()=>{
      // 연속적으로 타이핑을 칠 때마다 setFormIsValid가 실행되는 것을 방지하기 위해 setTimeOut으로 묶는다
      setFormIsValid(enteredEmail.includes('@') && enteredPassword.trim().length > 6);
    },500)
    

    // clean-up function
    // 첫 번째 SideEffect 함수가 실행되기 전에는 실행되지 않으며,
    // 2번째 side Effect 함수가 실행되기 전에, 그리고 컴포넌트가 제거되기 전에 실행된다.
    // clean-up function을 통해 두 번째 side Effect가 실행되기 전에 setTimeout을 삭제한다.
    return () => {
      clearTimeout(identifier);
    };

    //의존성 배열에 값을 추가하면 마지막 컴포넌트 랜더링 주기에서 해당 값이 변경된 경우에만 실행하라는 뜻이다.
    // setFormIsValid는 의존성 배열에 입력하지 않아도 되는데,
    // state를 업데이트하는 함수는 기본적으로 리엑트에 의해 절대 변경되지 않도록 보장하기 때문이다.
  },[enteredEmail,enteredPassword])

  	...
  return (
    ... 
    <div className={classes.actions}>
          {/* disabled={!formIsValid}는 현재 formIsValid값이 false이기때문에 disabled={true}인 상태. */}
          {/* formIsValid 조건이 충족된다면 disabled={false}로 잠김이 해제 된다. */}
          <Button type="submit" className={classes.btn} disabled={!formIsValid}>
            Login
          </Button>
        </div>
      </form>
    </Card>
  );
};

export default Login;

0개의 댓글