1.Programming
프로그래밍 적으로 컴포넌트를 분리한다면 단일 책임 원칙을 기준으로 컴포넌트를 분리한다.
단일 책임 원칙이란 모든 클래스는 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화해야 함을 일컫는다.
2.UI 재사용
동일한 UI구조가 여러곳에 쓰이면 분리해주는게 좋음
1.정적인 UI 먼저 구현
2.UI 컴포넌트 쪼개기
3.상호작용(이벤트 및 상태관리)
4.기능구현/API 연동
5.최종(유효성 검사,예외 처리)
해당 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는 정확히 두 개의 값을 가진 배열을 반환합니다.
const [state,setState] = useState('')
현재 state입니다. 첫 번째 렌더링 중에는 전달한 initialState와 일치합니다.
state를 다른 값으로 업데이트하고 리렌더링을 촉발할 수 있는 set 함수입니다.
이 개발 환경 전용 동작은 컴포넌트를 순수하게 유지하는 데 도움이 됩니다. React는 호출 중 하나의 결과를 사용하고 다른 호출의 결과는 무시합니다. 컴포넌트, 초기화 함수, 업데이터 함수가 순수하다면 이 동작이 로직에 영향을 미치지 않습니다. 반면 의도치 않게 순수하지 않을 경우에는 실수를 알아차리는 데 도움이 됩니다.
useEffect는 렌더링 이후에 실행되는 코드를 넣는 곳.
React 바깥의 일 (서버, 이벤트 등록, DOM 직접 조작 등)을 해야 할 때 사용함.
useEffect(() => {
// 마운트될 때 실행할 코드
return () => {
// 언마운드 될 때 실행할 코드 - 정리(cleanup) 함수 - 선택적
};
}, [의존성1, 의존성2, ...]); //의존성이 업데이트 되면 useEffect() 재 실행
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가 바뀔때 알아서 계산해줌.
const [buyClicked, setBuyClicked] = useState(false);
useEffect(() => {
if (buyClicked) {
fetch('/api/buy', { method: 'POST' });
alert('구매 완료!');
}
}, [buyClicked]);
이렇게 하면 버튼 클릭 → state 변경 → Effect 실행 → 요청 전송.
근데 문제는, Effect는 "렌더링 후에 실행"되기 때문에,
클릭 시점에 정확히 어떤 일이 있었는지 알 수 없음.
useEffect(() => {
fetch('/api/products')
.then(res => res.json())
.then(data => setProducts(data));
}, []);
ex) 페이지 들어오자마자 상품 목록 보여줘야 할 때
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) 해당 유저의 장바구니 및 위시리스트는 다 다르기 때문에 다르게 불러와야함.
[]: 컴포넌트가 마운트될 때 한 번만 실행, 언마운트 시 정리 함수 실행[value1, value2]: 해당 값들이 변경될 때마다 실행React의 onClick 와 같은 이벤트는 React가 컴포넌트 생명주기 따라 자동으로 등록하고 정리해주기 떄문에 클린업 할 필요가 없다!!
useRef는 DOM에 대한 참조가 주된 목적인데 useRef는 변수를 만들어서 컴포넌트가 리렌더링되어도 값을 유지할 수 있게 해줌. ref는 컴포넌트의 시각적 출력에 영향을 미치지 않는 정보를 저장하는 데 적합하다.
const ref = useRef(초기값);
접근은ref.current로 접근한다
import { useRef, useEffect } from 'react';
function InputFocus() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus(); // 마운트 시 자동 포커스
}, []);
return <input ref={inputRef} />;
}
마운트 시 바로 원하는 input에 포커스 시켜 사용자 경험을 증가시키는 방법이다.