본문 바로가기
WEB/Front-end

React_useEffect, useReducer, 최적화 (React.js)

by 최새벽 2024. 7. 11.



#01. 리액트 컴포넌트 라이프 사이클

 

개발자 도구 - Profiler에서 라이프사이클 확인할 수 있음

 

- (생성) 마운트: 컴포너트를 페이지에 처음 랜더링 할 때

- 업데이트: State/Props의 값이 바뀌거나 부모 컴포넌트가 리랜더되어 본인도 리랜더 될 때

- (소멸)언마운트: 더 이상 페이지에 컴포넌트를 랜더링하지 않을 때. 사라짐.

 

[useEffect] 

값의 변경이 생길 때 마다 특정 코드를 실행하는 리액트 훅

  // useEffect(함수, 의존성배열);
  // 배열안에 들어간 변수가 바뀌면 앞의 함수가 실행
  useEffect(() => {
    console.log("count 업데이트:", count);
    console.log("text 업데이트:", text);
  }, [count, text]);

 

- 의존성 배열을 안넣을 경우: 변화가 일어날 때마다 useEffect실행

  useEffect(() => {
    console.log("컴포넌트 업데이트");
  });

 

- 마운트 시점과 업데이트 시점을 다르게 제어

  const didMountRef = useRef(false);
    if (!didMountRef.current) {
      didMountRef.current = true;
      return;
    } else {
      console.log("컴포넌트 업데이트");
    }
  });

  useEffect(() => {
    console.log("컴포넌트 마운트");
  }, []); // 빈 의존성 배열 : 의존성의 값을 안주겠다. ==> 맨 처음 한번만 실행

 

- setInterval을 통한 setEffect 제어

: setInterval의 콜백함수가 1초에 한번 콘솔을 찍는 함수 실행

: 다른 이벤트 일어나면 함수가 중첩돼서 동시에 스레드처럼 여러번 출력됨

     => 빠르게 출력 여러번 되는 것 처럼 보임

  useEffect(() => {
    // useEffect의 콜백 함수가 setInterval 함수 실행
    // (274p참고)
     setInterval(() => {
      console.log("깜빡");
    }, 1000);
  });

 

- 함수 변수를 선언하여 초기화하기

: intervalID를 선언하여 이벤트를 통한 interval함수가 중첩되지 않게 방지, 새 인터벌을 생성하여 기존 인터벌을 삭제하는 것

  useEffect(() => {
  const intervalID = setInterval(() => {
      console.log("깜빡");
    }, 1000);
    return () => {
      console.log('클린업');
      clearInterval(intervalID);
    }
  });

 

- 언마운트 제어하기

return (
    <div className="App">
      <h1>Simple Counter</h1>
      <section>
        <input value={text} onChange={handleOnChanageText} />
      </section>
      <section>
        <Viewer count={count} />
        {/* Even은 그냥 컴포넌트. 아래와 같이 하면 왼쪽 조건이 충족될 때 오른쪽 컴포넌트가 실행됨 */}
        {/* And 연산은 왼쪽 조건이 false일 때 오른쪽을 실행하지 않는다는 특성을 활용 */}
        {count % 2 === 0 && <Even />}
      </section>
      <section>
        <Controller handleSetCount={handleSetCount} />
      </section>
    </div>
  );

 

import { useEffect } from "react";

// 바로 export할 수 있음
export default () => {
  useEffect(() => {
    return () => {
      console.log("Even 컴포넌트 언마운트");
    };
  }, []);
  return <div>현재 카운트는 짝수입니다.</div>;
};

 

 

#02. useReducer

 

[useReducer]

import { useReducer } from "react";

function reducer(state, action) {
  switch (action.type) {
    case "INCREASE":
      return state + action.data;
    case "DECREASE":
      return state - action.data;
    default:
      return state;
  }
}

function TestComp() {
  const [count, dispatch] = useReducer(reducer, 0);

  return (
    <div>
      <h4>테스트 컴포넌트</h4>
      <div>
        <bold>{count}</bold>
      </div>
      <div>
        <button onClick={() => dispatch({ type: "INCREASE", data: 1 })}>
          +
        </button>
        <button onClick={() => dispatch({ type: "DECREASE", data: 1 })}>
          -
        </button>
      </div>
    </div>
  );
}

export default TestComp;

- count: state 변수

- dispatch: 상태 변화 촉발 함수, 함수가 호출되면 인수로 객체를 전달(상태 변화 함수로 객체 전달해서 실행시키는 역할)

- useReducer(상태 변화 함수, 초깃값)

- 위의 방식을 사용하면 비슷한 결의 새로운 기능을 추가할 때 함수를 새로 만드는 것이 아니라 case를 추가하기만 하면 된다.

 

#03. 최적화

 

[최적화]

웹 서비스의 성능을 개선, 사용자의 불필요한 대기 시간을 줄이고 사용자 경험을 긍정적으로 개선

- useMemo: 메모리제이션 기법을 이용해서 연산의 결값을 저장. 동일 요청이 들어오면 결괏값을 빠르게 응답

 

[고차 컴포넌트와 횡단 관심사]

React.memo

 

-HOC: Higher Order Component, 인수로 전달된 컴포넌트를 새로운 컴포넌트로 반환하는 함수

어떤 기능을 추가해서 반환

강화된 컴포넌트라고 함

 

-횡단 관심사: 크로스 커팅 관심사 Cross-Cutting Concerns

비즈니스 로직과 공통된 기능을 구분

중복코드를 줄일 수 있음

 

- 다음과 같이 React.memo하면 지속적인 리랜더링이 일어나지 않음

import './Header.css';
import React from 'react';

export default React.memo(() => {
    console.log('header');
    return (
        <div className="Header">
            <h3>오늘은 📅</h3>
            <h1>{new Date().toDateString()}</h1>
        </div>
    );
});

- React.memo가 값이 변화한지 안한지 판단하는 요소: Property

 

[useCallback]

불필요한 상황에서 리랜더 방지

useCallback(함수, []);

 

[최적화 규칙]

- 최적화는 꼭 필요할 때만 하기 : 오히려 더 복잡해져서 문제 일으킬 수도

- 최적화는 가장 마지막에

- 컴포넌트 구조 잘 설계했는지 확인하기

 

 

 

 

 

 

 

 

'WEB > Front-end' 카테고리의 다른 글

HTML 기초 (HTML, CSS, JS)  (0) 2024.07.18
CSS 기초 (HTML, CSS, JS)  (0) 2024.07.18
React 서버 배포, React 기초 (React.js)  (0) 2024.07.09
React 시작하기 (React.js)  (1) 2024.07.08
티스토리 커서 모양 바꾸기  (1) 2024.02.29