(React) Side effects

soosoorim·2024년 5월 20일

Side effects

  • 어떤 함수가 실행됨으로써 화면의 변화가 일어나는 것
  • React Component는 Props와 State가 변경될 경우, Component를 재 실행해 화면을 다시 그린다.
    => Side Effect

  • 비동기 통신 또는 이벤트에 의해 Props혹은 State가 변경될 경우 Component를 무한히 재실행하는 부작용이 생길 수 있다.

REST API를 이용해 응답을 받아와 State에 할당해보기

에러가 발생하는 원인
State / Props가 변경되면 해당 컴포넌트는 항상 재실행 된다.

무한반복 에러 해결 방법

  • 특별한 상황일 때 만 state가 변경되도록 한다.

컴포넌트가 처음 실행되면 fetch해, state를 변경한다.

  • App.js

useEffect 를 사용해주면 무한반복을 멈출 수 있다.

  • Header.js
import { useRef, useEffect } from "react";

export default function Header({ token, setToken }) {
  const emailRef = useRef();
  const passwordRef = useRef();

  // 이 컴포넌트가 실행되자마자 Local Storage에 token 값이 있는지 확인한다.
  // Token 값이 있다면 token state에 값을 할당.
  useEffect(() => {
    const storedToken = localStorage.getItem("token");
    if (storedToken) {
      setToken(storedToken);
    }
  }, [setToken]);

  const onLoginClickHandler = async () => {
    const email = emailRef.current.value;
    const password = passwordRef.current.value;

    if (!email) {
      alert("Email을 입력하세요.");
      emailRef.current.focus();
      return;
    }

    if (!passwordRef) {
      alert("비밀번호를 입력하세요.");
      passwordRef.current.focus();
      return;
    }

    const response = await fetch("http://localhost:8080/auth/token", {
      method: "POST",
      body: JSON.stringify({ email, password }),
      headers: { "Content-Type": "application/json" },
    });

    const json = await response.json();
    setToken(json.token);

    // token의 값을 브라우저의 로컬 스토리지에 작성한다.
    localStorage.setItem("token", json.token);

    // token의 값을 브라우저의 세션 스토리지에 작성한다. (같음)
    // sessionStorage.setItem("token", json.token);
  };

  return (
    <header>
      {token && <div>로그인이 완료되었습니다.</div>}
      {!token && (
        <div>
          <label htmlFor="email">EMAIL</label>
          <input type="email" id="email" placeholder="Email" ref={emailRef} />

          <label htmlFor="password">PASSWORD</label>
          <input
            type="password"
            id="password"
            placeholder="Password"
            ref={passwordRef}
          />

          <button onClick={onLoginClickHandler}>로그인</button>
        </div>
      )}
    </header>
  );
}

0개의 댓글