컴포넌트가 렌더링 될때마다 특정작업을 실행할 수 있도록 하는 HOOK
import { useEffect, useState } from "react"; import { useRouter } from "next/router"; export default function FunctionalCounterPage(): JSX.Element { const [count, setCount] = useState(100); const router = useRouter(); //------------------------------------------------------------------ 1. DidMount - 컴포넌트가 화면에 처음 렌더링 될 때 한 번만 실행 useEffect(() => { console.log("마운트 실행"); },[]); //------------------------------------------------------------------ 2. DidUpdate - 뭐 하나라도 바뀌면 실행됨.대괄호 없음 useEffect(() => { console.log("수정되고 다시 그리기 실행"); }); //------------------------------------------------------------------ 3. WillUnmount - 컴포넌트 사라질때 // 1번과 모양이 같이 때문에 하나로 합치기 가능 useEffect(() => { //이 부분이 끝나고 진행할 것들 return() =>{ console.log("수정되고 다시 그리기 실행"); } },[]);// [] : 의존성 배열(dependency-array) //------------------------------------------------------------------ //[count]라면? 처음 실행 후 count가 바뀔 때만 실행 useEffect(() => { console.log("업뎃"); },[count]); //------------------------------------------------------------------ 4. DidMount + WillUnmount //두 시점에서 실행이 됨 useEffect(() => { console.log("마운트 실행"); return () =>{ console.log("컴포넌트 사라짐!!!") } },[]); //------------------------------------------------------------------ const onClickCountUp = (): void => { console.log(count); setCount(1); }; const onClickMoveOut = (): void => { void router.push("/"); }; console.log("내가 제일 먼저 실행되지~!"); return ( <> <div>{count}</div> <button onClick={onClickCountUp}>UP!</button> <button onClick={onClickMoveOut}>OUT!</button> </> ); }
✅ 의존성 배열(dependency-array)
: 컴포넌트의 상태(state)가 다른 컴포넌트나 프로퍼티에 의존하는 경우,
의존성 배열을 사용하여 상태 변경에 따른 업데이트를 추적한다.
의존성 배열 인자에 따라 렌더가 달라지므로 의존성 배열을 잘다뤄야 한다.만일 useEffect에 의존성 배열을 적어주지 않고 return 또한 해주지 않는다면,
무한렌더 지옥에 빠지게 된다.
즉, 의존성 배열이 함수형 컴포넌트의 생명주기를 결정하는 뽀인뚜!!useEffect의 실행 시점❗️
→생명주기 메서드,hook 은 기본적으로 렌더(화면그리기) 이후에 실행됨.
useEffect와 lifecycle 메서드는 렌더 이후에 실행!
✅ useEffect 사용시 주의 사항
useEffect 안에서 setState의 사용
→useEffecrt 내에서 setState를 사용할때는 정말 필요한 경우가 아니라면 지양하는 것이 좋다.컴포넌트가 마운트된 이후에 setState를 적용하게 되면,
1. state가 변경되고,
2. 변경된 state로 컴포넌트가 다시그려지게(=리렌더) 된다.즉, useEffect 내에서 setState를 사용하게 되면
불필요한 리렌더나 무한루프를 일으키게 되고 성능면에서 비효율적임!!*******************************주의*********************************** // useEffect의 잘못된 사용법(1.추가렌더링, 2.무한루프) useEffect(() => { setCount((prev) => prev + 1); },[count]);
[실습]
import { useEffect, useState } from "react"; import { useRouter } from "next/router"; export default function LifeCyclePage(): JSX.Element { const [isChanged, setIsChanged] = useState(false); const router = useRouter(); useEffect(() => { alert("Rendered!"); }, []); useEffect(() => { return () => { alert("Bye!!"); }; }, []); const onClickChange = (): void => { alert("Changed!!"); setIsChanged(true); console.log(isChanged); }; const onClickMove = (): void => { router.push("/"); }; return ( <> <button onClick={onClickChange}>변경</button> <button onClick={onClickMove}>이동</button> </> ); }
//다른방법1 useEffect(() => { return () => { alert("Rendered!!"); }; }); //if 조건문으로 isChanged의 초기값에 따라 달라지도록 함. useEffect(() => { if (isChanged) { alert("Changed!!"); } }, [isChanged]); useEffect(() => { return () => { alert("Bye!!"); }; }, [router]);
//다른방법2 useEffect(() => { alert("Rendered!"); return () => { alert("Bye!!"); }; }, []); useEffect(() => { alert("Changed!!"); / }, [isChanged]);
- axios를 이용해 get 해오기
- 브라우저가 실행되자마자 요청 하도록 useEffect 사용
import axios from "axios"; import { useEffect, useState } from "react"; export default function RestGetPage(): JSX.Element { const [dog, setDog] = useState(""); useEffect(() => { // async를 붙이기 위해 함수를 선언하고, 만든 함수를 실행시킨다. const onClickSync = async (): Promise<void> => { const result = await axios.get("https://dog.ceo/api/breeds/image/random"); console.log(result.data.message); //사진주소 setDog(result.data.message); }; void onClickSync(); }, []); return ( //jsx <div> <img src={dog} /> {/* <button onClick={onClickSync}>REST-API(동기)요청하기</button> */} </div> ); }
요즘 추세!
reactQuery => useQuery
apolloClient => useQuery