- Published on
리액트 공식문서 스터디 9-1 주차
- Authors

- Name
- junyeol kim
Removing Effect Dependencies
Dependencies should match the code
Effect 코드 내부에서 읽는 모든 반응형 값은 반드시 의존성 목록에 포함되어야 한다.
linter는 코드에서 사용하는 반응형 값이 의존성에 누락되었는지 확인하여 동기화 버그를 방지한다.
의존성이 코드와 일치하지 않으면 버그가 발생할 위험이 높으므로 linter를 억제하지 말아야 한다.
To remove a dependency, prove that it’s not a dependency
의존성을 제거하려면 해당 값이 반응형 값이 아니라는 것을 linter에 증명해야 한다.
값을 컴포넌트 외부로 이동시키면 재렌더링 시에도 값이 변하지 않으므로 의존성에서 제거할 수 있다.
반응형 값에는 props와 컴포넌트 내부에서 직접 선언된 변수 및 함수가 포함된다.
To change the dependencies, change the code
의존성 목록은 사용자가 선택하는 것이 아니라 Effect의 코드에 의해 결정된다.
의존성을 변경하고 싶다면 먼저 Effect의 코드나 반응형 값의 선언 방식을 변경해야 한다.
코드를 수정한 후 그 결과에 맞춰 의존성 목록을 조정하는 과정이 필요하다.
Removing unnecessary dependencies
의존성 중 하나가 변경될 때마다 Effect가 다시 실행되는 것이 합리적인지 검토해야 한다.
Should this code move to an event handler?
문제: 알림 스타일을 위한 theme이 의존성에 포함되면, 테마만 바꿔도 다시 알림이 전송되는 버그가 발생한다.
해결: 상호작용(제출)에만 반응하도록 로직을 이벤트 핸들러로 옮긴다.
function Form() {
const theme = useContext(ThemeContext);
function handleSubmit() {
// 이벤트 핸들러에서 직접 실행하여 theme 변경에 반응하지 않게 함
post('/api/register');
showNotification('Successfully registered!', theme);
}
// ...
}
Is your Effect doing several unrelated things?
문제: 한 Effect에서 country와 city를 모두 관리하면 도시만 바꿔도 도시 목록까지 다시 불러온다.
해결: 각각의 동기화 프로세스를 별도의 Effect로 분리한다.
function ShippingForm({ country }) {
const [cities, setCities] = useState(null);
useEffect(() => {
// country 변경 시 도시 목록 가져오기
fetch(`/api/cities?country=${country}`).then(/* ... */);
}, [country]);
const [city, setCity] = useState(null);
const [areas, setAreas] = useState(null);
useEffect(() => {
// city 변경 시 지역 목록 가져오기
if (city) fetch(`/api/areas?city=${city}`).then(/* ... */);
}, [city]);
// ...
}
Are you reading some state to calculate the next state?
문제: messages를 직접 참조하면 새 메시지가 올 때마다 Effect가 재실행되어 연결이 계속 끊긴다.
해결: 업데이터 함수를 사용하여 messages를 의존성에서 제거한다.
function ChatRoom({ roomId }) {
const [messages, setMessages] = useState([]);
useEffect(() => {
const connection = createConnection();
connection.connect();
connection.on('message', (receivedMessage) => {
// 이전 상태를 인자로 받아 업데이트
setMessages(msgs => [...msgs, receivedMessage]);
});
return () => connection.disconnect();
}, [roomId]); // messages 의존성 제거
// ...
}
Do you want to read a value without "reacting" to its changes?
문제: isMuted가 바뀔 때마다 채팅방에 다시 연결되는 비합리적인 동작이 발생한다.
해결: useEffectEvent로 비반응형 로직을 분리한다.
function ChatRoom({ roomId }) {
const [isMuted, setIsMuted] = useState(false);
// 최신 값은 읽되 변경에 반응은 하지 않는 로직 추출
const onMessage = useEffectEvent(receivedMessage => {
if (!isMuted) playSound();
});
useEffect(() => {
const connection = createConnection();
connection.on('message', (msg) => onMessage(msg));
connection.connect();
return () => connection.disconnect();
}, [roomId]); // isMuted에 반응하지 않음
// ...
}
Does some reactive value change unintentionally?
문제: 렌더링 때마다 생성되는 객체나 함수를 의존성에 넣으면 매번 Effect가 재실행된다.
해결: 객체를 Effect 내부로 옮기거나 원시 값을 의존성으로 사용한다.
function ChatRoom({ roomId }) {
useEffect(() => {
// 객체를 Effect 내부에서 선언하여 의존성에서 제외
const options = {
serverUrl: 'https://localhost:1234',
roomId: roomId
};
const connection = createConnection(options);
connection.connect();
return () => connection.disconnect();
}, [roomId]); // 객체 대신 원시값인 roomId에만 반응
// ...
}