[React] React 공식문서 읽기

김민석·2025년 4월 9일
post-thumbnail

React

컴포넌트 분리하기

컴포넌트 분리하는 기준

1.Programming
프로그래밍 적으로 컴포넌트를 분리한다면 단일 책임 원칙을 기준으로 컴포넌트를 분리한다.
단일 책임 원칙이란 모든 클래스는 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화해야 함을 일컫는다.
2.UI 재사용
동일한 UI구조가 여러곳에 쓰이면 분리해주는게 좋음

React 개발 순서

1.정적인 UI 먼저 구현
2.UI 컴포넌트 쪼개기
3.상호작용(이벤트 및 상태관리)
4.기능구현/API 연동
5.최종(유효성 검사,예외 처리)

React State 위치 결정

해당 state를 쓰는 컴포넌트를 확인하고 여러 컴포넌트가 사용하면 공통 부모에 state를 사용하는 것이 좋다. 너무 복잡하거나 전역에서 쓰는 state는 redux 나 context 같은 상태관리 라이브러리를 사용하는 것도 좋은 방법이다.

왜 컴포넌트를 순수하게 유지해야할까??

순수함수란?

입력이 같으면 항상 같은 출력을 반환하면서 함수 외부의 상태를 변경하지 않음

// 순수 함수 예시
function add(a, b) {
  return a + b; 
}

// 순수하지 않은 함수 (외부 상태 변경)
let count = 0;
function addCount(a) {
  count += a; 
  return count;
}

컴포넌트는 주어진 props와 state를 기반으로 UI를 예측이 가능하도록 만ㄷ르어야한다.
그렇지 않으면 예측이 불가능해지고 디버깅에 어려움이 생깁니다!

useState

useState는 정확히 두 개의 값을 가진 배열을 반환합니다.
const [state,setState] = useState('')
현재 state입니다. 첫 번째 렌더링 중에는 전달한 initialState와 일치합니다.
state를 다른 값으로 업데이트하고 리렌더링을 촉발할 수 있는 set 함수입니다.

초기화 함수 또는 업데이터 함수가 두 번 실행?

이 개발 환경 전용 동작은 컴포넌트를 순수하게 유지하는 데 도움이 됩니다. React는 호출 중 하나의 결과를 사용하고 다른 호출의 결과는 무시합니다. 컴포넌트, 초기화 함수, 업데이터 함수가 순수하다면 이 동작이 로직에 영향을 미치지 않습니다. 반면 의도치 않게 순수하지 않을 경우에는 실수를 알아차리는 데 도움이 됩니다.

useEffect

useEffect는 렌더링 이후에 실행되는 코드를 넣는 곳.
React 바깥의 일 (서버, 이벤트 등록, DOM 직접 조작 등)을 해야 할 때 사용함.

기본구조

useEffect(() => {
  // 마운트될 때 실행할 코드 
  return () => {
  // 언마운드 될 때 실행할 코드 -  정리(cleanup) 함수 - 선택적
  };
}, [의존성1, 의존성2, ...]); //의존성이 업데이트 되면 useEffect() 재 실행

useEffect는 꼭 필요한 경우에만 사용해야 한다 그럼 어느 상황에서 사용해야할까??

렌더링을 위해 데이터를 변환할 때 사용 X

const [filteredList, setFilteredList] = useState([]);

useEffect(() => {
  const filtered = list.filter(item => item.active);
  setFilteredList(filtered);
}, [list]);

이렇게 하면 list가 바뀔 때마다 setFilteredList()가 호출되고,
state가 바뀌면 다시 렌더링 → useEffect 실행 → 또 state 업데이트 되면서
불필요한 렌더링이 계속 발생함.

const filteredList = list.filter(item => item.active);

그냥 이렇게 하면 React가 list가 바뀔때 알아서 계산해줌.

사용자 이벤트일 경우 사용 X

const [buyClicked, setBuyClicked] = useState(false);

useEffect(() => {
  if (buyClicked) {
    fetch('/api/buy', { method: 'POST' });
    alert('구매 완료!');
  }
}, [buyClicked]);

이렇게 하면 버튼 클릭 → state 변경 → Effect 실행 → 요청 전송.
근데 문제는, Effect는 "렌더링 후에 실행"되기 때문에,
클릭 시점에 정확히 어떤 일이 있었는지 알 수 없음.

useEffect로 API 요청하는 경우

컴포넌트가 처음 마운트됐을 때 데이터를 불러오는 경우

useEffect(() => {
  fetch('/api/products')
    .then(res => res.json())
    .then(data => setProducts(data));
}, []);

ex) 페이지 들어오자마자 상품 목록 보여줘야 할 때

어떤 state나 prop이 바뀔 때마다 API 요청이 필요할 때

useEffect(() => {
  fetch(`/api/search?query=${keyword}`)
    .then(res => res.json())
    .then(data => setResults(data));
}, [keyword]);

ex) 검색어 입력값이 바뀔 때 결과 새로 요청

라우팅 파라미터나 외부 값이 바뀌어서 데이터를 다시 불러와야 할 때

useEffect(() => {
  fetch(`/api/users/${userId}`)
    .then(res => res.json())
    .then(data => setUser(data));
}, [userId]);

ex) 해당 유저의 장바구니 및 위시리스트는 다 다르기 때문에 다르게 불러와야함.

1. 실행 시점

  • 마운트 시: 컴포넌트가 처음 화면에 나타날 때
  • 업데이트 시: 의존성 배열에 있는 값이 변경될 때 (의존성 배열이 제공된 경우)
  • 언마운트 시: 컴포넌트가 화면에서 사라질 때 (정리 함수 실행)

2. 의존성 배열

  • 빈 배열 []: 컴포넌트가 마운트될 때 한 번만 실행, 언마운트 시 정리 함수 실행
  • 의존성 포함 [value1, value2]: 해당 값들이 변경될 때마다 실행
  • 배열 생략: 모든 렌더링 후 실행 (일반적으로 권장하지 않음)

3. 정리(Cleanup) 함수

  • 이전 효과를 정리하기 위한 함수
  • 메모리 누수 방지에 중요
  • 이벤트 리스너, 타이머, 구독 등을 해제할 때 필요

React의 onClick 와 같은 이벤트는 React가 컴포넌트 생명주기 따라 자동으로 등록하고 정리해주기 떄문에 클린업 할 필요가 없다!!

useRef

useRef는 DOM에 대한 참조가 주된 목적인데 useRef는 변수를 만들어서 컴포넌트가 리렌더링되어도 값을 유지할 수 있게 해줌. ref는 컴포넌트의 시각적 출력에 영향을 미치지 않는 정보를 저장하는 데 적합하다.

const ref = useRef(초기값);

접근은ref.current로 접근한다

useRef 사용법

import { useRef, useEffect } from 'react';

function InputFocus() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus(); // 마운트 시 자동 포커스
  }, []);

  return <input ref={inputRef} />;
}

마운트 시 바로 원하는 input에 포커스 시켜 사용자 경험을 증가시키는 방법이다.

profile
나만의 기록장

0개의 댓글