자제해야 하는 케이스
Props에 기반한 상태 업데이트
// 🚫 잘못된 사용
function ProductCard({ price, quantity }) {
const [total, setTotal] = useState(0);
useEffect(() => {
setTotal(price * quantity);
}, [price, quantity]);
return <div>총 가격: {total}</div>;
}
// ✅ 개선: 렌더링 중에 직접 계산
function ProductCard({ price, quantity }) {
const total = price * quantity;
return <div>총 가격: {total}</div>;
}
Props를 State로 미러링
// 🚫 잘못된 사용
function UserProfile({ user }) {
const [userData, setUserData] = useState(user);
useEffect(() => {
setUserData(user);
}, [user]);
return <div>{userData.name}</div>;
}
// ✅ 개선: Props 직접 사용
function UserProfile({ user }) {
return <div>{user.name}</div>;
}
연쇄적인 상태 업데이트
// 🚫 잘못된 사용
function FilteredList({ items }) {
const [filteredItems, setFilteredItems] = useState([]);
const [selectedItem, setSelectedItem] = useState(null);
useEffect(() => {
setFilteredItems(items.filter(item => item.active));
}, [items]);
useEffect(() => {
setSelectedItem(filteredItems[0]);
}, [filteredItems]);
return <List items={filteredItems} selected={selectedItem} />;
}
// ✅ 개선: 파생 데이터로 처리
function FilteredList({ items }) {
const [selectedIndex, setSelectedIndex] = useState(0);
const filteredItems = useMemo(() =>
items.filter(item => item.active),
[items]
);
const selectedItem = filteredItems[selectedIndex];
return <List items={filteredItems} selected={selectedItem} />;
}
이벤트 핸들링 로직
// 🚫 잘못된 사용
function SearchComponent({ onSearch }) {
const [query, setQuery] = useState('');
useEffect(() => {
onSearch(query);
}, [query, onSearch]);
return <input value={query} onChange={e => setQuery(e.target.value)} />;
}
// ✅ 개선: 이벤트 핸들러에서 직접 처리
function SearchComponent({ onSearch }) {
const [query, setQuery] = useState('');
const handleChange = (e) => {
const newQuery = e.target.value;
setQuery(newQuery);
onSearch(newQuery);
};
return <input value={query} onChange={handleChange} />;
}
데이터 변환/포맷팅
// 🚫 잘못된 사용
function UserDisplay({ user }) {
const [formattedData, setFormattedData] = useState(null);
useEffect(() => {
setFormattedData({
fullName: `${user.firstName} ${user.lastName}`,
age: `${user.age}세`
});
}, [user]);
return <div>{formattedData?.fullName}</div>;
}
// ✅ 개선: 렌더링 중에 데이터 변환
function UserDisplay({ user }) {
const formattedData = {
fullName: `${user.firstName} ${user.lastName}`,
age: `${user.age}세`
};
return <div>{formattedData.fullName}</div>;
}
적절한 사용방식
외부 시스템 동기화
function ChatRoom({ roomId }) {
useEffect(() => {
const connection = createConnection(roomId);
connection.connect();
return () => connection.disconnect();
}, [roomId]);
}
브라우저 API
function WindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
}
데이터 페칭
function UserProfile({ userId }) {
const [data, setData] = useState(null);
useEffect(() => {
let ignore = false;
async function fetchData() {
const user = await fetchUser(userId);
if (!ignore) setData(user);
}
fetchData();
return () => ignore = true;
}, [userId]);
}
*GPT와의 채팅을 통해 정리한 글입니다.
'React' 카테고리의 다른 글
| 리액트 파이버의 동작 (0) | 2024.12.23 |
|---|---|
| 리액트 Hooks와 클로저 (0) | 2024.12.22 |
| React Props: 원시값 vs 참조값 비교하기 (0) | 2024.12.22 |
| useState vs useRef vs 일반 JS 초기화 (0) | 2024.04.15 |
| React DOM Element, ComponentElement (0) | 2024.04.15 |