본문 바로가기
REACT

[React] 272샘의 React13 ( useEffect Hook )

by 미눅스[멘토] 2024. 10. 11.
728x90

 

 

 

https://deahan.tistory.com/432

 

[React] 272샘의 React12 ( useRef Hook )

https://deahan.tistory.com/431 [React] 272샘의 React11 ( useState Hook )https://deahan.tistory.com/430 [React] 272샘의 React10 ( 레이아웃, children )https://deahan.tistory.com/429 [React] 272샘의 React9 ( Props 구조 분해 )https://deahan.ti

deahan.tistory.com

까지 아니 벌써 다 읽었다면,

12(12개월)는 소우주를 60(환갑)은 대우주를 경험한 것이니, 이제

당신의 손가락은  뇌의  간헐적 도움만으로도 화면을 지배할 느끼미를 가짐

 

보통 사이드효과라 불리는 useEffect 훅(Hook)을 훅하고 알아보자

재미가 쏠쏠하다.

 

Counter3.jsx

 
import { useEffect, useState } from "react";
import MyButton from "./MyButton";

function Counter3() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(`안녕 경미니 ${count}`);
  });

  return (
    <>
      <h1>
        경미니 <span style={{ color: "red" }}>{count}</span>번 호출
      </h1>
      <MyButton
        style={{ color: "yellow" }}
        onClick={() => {
          setCount(count + 1);
        }}
      >
        클릭
      </MyButton>
    </>
  );
}

export default Counter3;
 

 App.jsx

 
import Counter3 from "./Counter3";

function App() {
  return (
    <div>
      <Counter3 />
    </div>
  );
}

export default App;
 

결과가 시선을 원한다.

클릭을 누를때 마다 useEffect 안 console.log가 실행됨을 알 수 있다.

이것은 무슨 의미?  count 변수는  useState hook을 사용했기 때문에 reactive 변수다

곧 이 값이 바뀌면, Count3는 다시 그려지게 된(re-rendering).

다시 그려질 때 마다 실행되었단 의미가 의미 심장하다

 

Counter3.jsx 의 useEffect 부분만 아래 처럼 살짝 수정해보자

(눈에 거슬리는 밑줄이 생긴다면 ,일단 마구 무시해 버리자)

 
  useEffect(() => {
    console.log(`안녕 경미니 ${count}`);
  }, []);
 

결과를 다시 확인하면, 버튼을 눌러도 console.log가 딱 1번 밖에 찍혀있음을 안다.

곧 처음에만 한번 실행되고, 다시 그려질 땐 실행되지 않는다.

 

다시 아래 처럼 추가 수정을 해보자.

 
  useEffect(() => {
    console.log(`안녕 경미니 ${count}`);
  }, [count]);
 

결과를 다시 확인해 보면 버튼을 누를 때 마다 console.log가 다시 찍힘이 보인다.

, [ count ]);  부분을 디펜던시(dependecy)라 부르는데

 배열안에 있는 변수 값이 바뀔때마다 실행한다는 의미다.

 

Counter3.jsx 를 아래 처럼 수정해보자( count2  추가에 주목)

 
import { useEffect, useState } from "react";
import MyButton from "./MyButton";

function Counter3() {
  const [count, setCount] = useState(0);
  const [count2, setCount2] = useState(0);

  useEffect(() => {
    console.log(`안녕 경미니 ${count}`);
  }, [count]);

  return (
    <>
      <h1>
        경미니{" "}
        <span style={{ color: "red" }}>
          {count} {count2}
        </span>
        번 호출
      </h1>
      <MyButton
        style={{ color: "yellow" }}
        onClick={() => {
          setCount(count + 1);
        }}
      >
        클릭
      </MyButton>
      <MyButton
        style={{ color: "pink" }}
        onClick={() => {
          setCount2(count2 + 1);
        }}
      >
        눌러유
      </MyButton>
    </>
  );
}

export default Counter3;
 

결과를 확인하면, 클릭을 누르면 로그가 나오지만, 눌러유는 로그가 안나온다.

, [ count ]); 를 , [ count, count2]); 로 고쳐서도 한번 해보자. Good!

분명 뇌가 반짝였을것이다.

 

한개 더 맛을 보자. useEffect(...) 부분을 아래처럼 고친다

 
  useEffect(() => {
    console.log(`안농 경미니 ${count}`);

    // 요건 언제 실행 되어용
    return () => {
      console.log(`미누가 좋으니 ${count}`);
    };
  }, [count]);
 

결과를 확인해 보기 바란다.

 

이제 정리를 해볼 시간이다  

useEffect의 2번째 매개변수를 안 주면 그려질 때 마다 실행되고,

빈 배열 []을 주면, 처음 그려질 때(rendering) 1번만 실행되고,

배열안에 값을 주면 해당 값에 변화가 생길때만 실행된다.

useEffect 안에서 return 되는 함수의 로그도 보았을 것이다.(이것은 뭐지?)

 

조금 더 정확히 이야기 하면 영어로는 mount / unmount 라는 표현을 쓰는데,장착 / 제거 라는

의미로 컴퓨터에 하드디스크등을 다는 것을 mount라 하고 빼는 것을 unmount라고 하였다.

이 표현을 빌려서 HTML 문서에 곧 document 객체에 DOM Element를 

추가하는 것을 mount, 제거하는 것을 unmount라고 하는데.

mount 될 때(append, appendChild...) 실행되는 것이 useEffect(..) 안의 코드고,

unmount(remove, removeChild...) 될 때 return 된 함수가 실행된다. 

말이 어렵다?, 괜찮다!   시간은 항상 젊디 젊은  당신(아직 환갑 머나 멈) 편이다.

(페이스북 개발자들도 평균 3개월을 소비했다니..) 

 

Counter3.jsx 를 아래 처럼 수선한 뒤 결과 확인

 
import { useEffect, useState } from "react";
import MyButton from "./MyButton";

function Counter3() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(`안농 경미니 ${count}`);

    // 요건 언제 실행 되어용
    return () => {
      console.log(`미누가 좋으니 ${count}`);
    };
  }, [count]);

  return (
    <>
      <h1>
        경미니{" "}
        <span style={{ color: "red" }}>{count}</span>
        번 호출
      </h1>
      <MyButton
        style={{ color: "yellow" }}
        onClick={() => {
          setCount(count + 1);
        }}
      >
        클릭
      </MyButton>
      <MyButton
        style={{ color: "pink" }}
        onClick={() => {
          setCount(0);
        }}
      >
        0으로 초기화
      </MyButton>
    </>
  );
}

export default Counter3;
 

useEffect를 어디에 쓰면 좋을지 꼭 한번 고민해 보기 바람. (???)

 

 

React  코딩 스타일에 익숙해지기 위해서 한 걸음만 더 나가보자.

아래 명령어로 faker(더미 데이터 생산용) 모듈을 개발용 Dependency로 설치 하자

npm install -D @faker-js/faker

덩말로 궁금하다면 아래 링크 방문하면 된다... 

https://www.npmjs.com/package/@faker-js/faker

 

Counter3.jsx 를 아래와 같이 새로 작성.(길지만 이미 거의 아는 내용)

 
import { useEffect, useRef, useState } from "react";
import MyButton from "./MyButton";
import { faker } from "@faker-js/faker/locale/ko";

// 바꾸지 않을 값이라면 function밖에 또는(선택) 안에 써도 된당.
const bestFriens = [
  { fid: "f001", name: "경미닝", age: 24, avatar: "energy" },
  { fid: "f002", name: "미누니", age: 42, avatar: "like" },
  { fid: "f003", name: "선주니", age: 29, avatar: "search" },
  { fid: "f004", name: "병처니", age: 27, avatar: "alcohol" },
];

// faker-js 이용
const person = faker.person;

function Counter3() {
  let fid = useRef(1);

  const [myFriend, setMyFriend] = useState(bestFriens);

  useEffect(() => {
    //console.log(`안농 경미니`);

    return () => {
      //console.log(`미누가 좋으니`);
    };
  }, [myFriend]);

  const addFriend = () => {
    const pName = person.firstName();
    const friend = {
      fid: `new${fid.current++}`,
      name: pName,
      age: Math.floor(Math.random() * 40) + 20,
      avatar: pName,
    };

    console.log("체크:", friend);

    const friends = [friend, ...myFriend];
    setMyFriend(friends);
  };

  return (
    <>
      <MyButton onClick={addFriend}>친구 추가</MyButton>
      <MyButton
        onClick={() => {
          setMyFriend([]);
        }}
      >
        친구 클리어
      </MyButton>
      {myFriend.length != 0 ? (
        myFriend
          .filter((friend) => friend.age < 40)
          .map((friend) => (
            <div key={friend.fid}>
              <span style={{ fontWeight: "bold" }}>{friend.name}</span>
              <img
                src={`${avatarURL}${friend.name}`}
                width={200}
                height={200}
              />
            </div>
          ))
      ) : (
        <h1>금수저 친구 떠남</h1>
      )}
    </>
  );
}

export default Counter3;
 

결과에 시선이 별로 끌리지만 눌러본다.

filter(나이 40이하)로 미누를 골라낸 다음 3명을 화면에 그린다.

 

눈에 쌍심지를 꼬치처럼 세우고 봐야 할 부분은 아래다.

const friends = [friend, ...myFriend]; 
// myFriend.push(friend)  // 윗 줄을 주석처리 하고 이렇게 쓴다면...?? 반드시 해보길

setMyFriend(friends);

 ... 전개 연산자(Spread Operator)가 이해가 안된다면

2023.06.14 - [자바스크립트] - 시베리안 허숙희의 자바스크립트 비기닝 18 (구조 분해 등등..)

필히 필사적으로 글을 딱딱 씹어서 읽고 먹고 와야 한다.

 

꽤 중요한 부분인뎅.....  주석된 부분을 열고, 그 윗줄을 주석 처리하면

코드가 제대로 동작하지 않는다.  React는 같은 객체[여기선 배열]가 오면 변화가 없다고 판단한다.

새로운 객체를 할당해 주어야 한다.  중요하다면 그렇다면 기억하자.

이렇게 하는 이유는 메모리는 조금더 소비되겠지만, 객체 변화 history추적이 용이하다.

e7e샘은 정말 천재인가..

 

 

출처 : https://e-7-e.tistory.com/261