기술 블로그
react의 실수하기 쉬운 안티패턴과 파훼법 본문
반응형
1. 상태가 다른 상태를 바꾸는 패턴 (useEffect 안에서 setState)
const [a, setA] = useState(0);
const [b, setB] = useState(0);
useEffect(() => {
setB(a * 2);
}, [a]);
- 문제: 다른 값으로부터 계산 가능한 값을 굳이 상태로 두면 무한 루프 위험 + 중복 관리 필요
- 해결: 계산은 상태로 두지 않고 직접 계산
const [a, setA] = useState(0);
const b = a * 2; // 혹은 useMemo
2. 상태를 지나치게 잘게 나눈 경우
const [email, setEmail] = useState('');
const [isValid, setIsValid] = useState(false);
- 문제: 서로 연결된 값이 따로 관리되면 동기화 문제 발생
- 해결: 하나의 객체로 묶어서 관리
const [form, setForm] = useState({ email: '', isValid: false });
const handleChange = (email: string) => {
setForm({ email, isValid: validateEmail(email) });
};
3. useEffect로 데이터 가공하기
useEffect(() => {
const filtered = list.filter(item => item.active);
setFilteredList(filtered);
}, [list]);
- 문제: 단순히 계산 가능한 값을 effect와 state로 억지로 분리
- 해결: 렌더링 과정에서 계산
const filteredList = useMemo(
() => list.filter(item => item.active),
[list]
);
4. 렌더링 중에 비동기 호출
const data = fetch('/api/data'); // ❌ 렌더마다 실행
- 문제: 무한 호출 발생
- 해결: useEffect 안에서 처리
useEffect(() => {
fetch('/api/data').then(res => setData(res));
}, []);
5. 조건부로 훅 호출
if (isOpen) {
const [value, setValue] = useState(0); // ❌
}
- 문제: 훅은 항상 같은 순서로 실행돼야 함
- 해결: 훅은 최상단에 두고 조건은 렌더링 단계에서 처리
const [value, setValue] = useState(0);
if (!isOpen) return null;
6. props를 그대로 상태로 복사
function Child({ initialValue }) {
const [value, setValue] = useState(initialValue); // ❌ 부모 값 변경시 동기화 안 됨
}
문제: 부모 값이 바뀌어도 동기화 안 됨
해결:
- props를 직접 사용
- 정말 독립적인 값이어야 한다면 이름을
defaultValue
처럼 명확히 - 필요하다면 의도적으로
useEffect
로 갱신
7. 불필요한 리렌더
원인:
- Context에 큰 객체를 넣어서 전달
- 매번 새로운 함수나 객체를 만들어서 props로 전달
해결:
React.memo
,useCallback
,useMemo
로 최적화- Context는 작은 단위로 쪼개서 관리
반응형
Comments