반응형 의존성 지정
serverUrl 또는 roomId가 변경되면 Effect는 새 값을 사용하여 채팅에 다시 연결한다. // This is a reactive value
function ChatRoom({ roomId }) {
// This is a reactive value too
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
// This Effect reads these reactive values
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => connection.disconnect();
// ✅ So you must specify them as dependencies of your Effect
}, [serverUrl, roomId]);
// ...
}
roomId와 serverUrl은 반응형 값이기 때문에 의존성 목록에서 제거할 수 없다. function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => connection.disconnect();
}, []); // 🔴 React Hook useEffect has missing dependencies: 'roomId' and 'serverUrl'
// ...
}
serverUrl을 컴포넌트 밖으로 이동시킴으로써 반응형이 아니며 리렌더링시에도 const serverUrl = 'https://localhost:1234'; // Not a reactive value anymore
function ChatRoom({ roomId }) {
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => connection.disconnect();
}, [roomId]); // ✅ All dependencies declared
// ...
}
serverUrl은 반응형 값이 아니므로 의존성이 될 필요가 없다. const serverUrl = 'https://localhost:1234'; // Not a reactive value anymore
const roomId = 'music'; // Not a reactive value anymore
function ChatRoom() {
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => connection.disconnect();
}, []); // ✅ All dependencies declared
// ...
}
Pitfall | 함정
useEffect(() => {
// ...
// 🔴 Avoid suppressing the linter like this:
// eslint-ignore-next-line react-hooks/exhaustive-deps
}, []);
반응형 의존성 전달 예시
- 의존성 배열 전달하기
- 의존성을 지정하면서 Effect는 초기 렌더링 후 및 변경된 의존성으로 다시 렌더링한 후에 실행된다.useEffect(() => { // ... }, [a, b]); // Runs again if a or b are different
- 아래 예시에서
serverUrl과roomId는 반응형 값이므로 둘 다 의존성으로 지정해야 한다.- 따라서 드롭다운에서 다른 방을 선택하거나 서버 URL 입력을 수정하면 채팅이 다시 연결된다
- 하지만
message는 Effect에서 사용되지 않으므로 메시지를 편집해도 채팅에 다시 연결되지 않는다.// App.js . import { useState, useEffect } from 'react'; import { createConnection } from './chat.js'; . function ChatRoom({ roomId }) { const [serverUrl, setServerUrl] = useState('https://localhost:1234'); const [message, setMessage] = useState(''); . useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => { connection.disconnect(); }; }, [serverUrl, roomId]); . return ( <> <label> Server URL:{' '} <input value={serverUrl} onChange={e => setServerUrl(e.target.value)} /> </label> <h1>Welcome to the {roomId} room!</h1> <label> Your message:{' '} <input value={message} onChange={e => setMessage(e.target.value)} /> </label> </> ); } . export default function App() { const [show, setShow] = useState(false); const [roomId, setRoomId] = useState('general'); return ( <> <label> Choose the chat room:{' '} <select value={roomId} onChange={e => setRoomId(e.target.value)} <option value="general">general</option> <option value="travel">travel</option> <option value="music">music</option> </select> <button onClick={() => setShow(!show)}> {show ? 'Close chat' : 'Open chat'} </button> </label> {show && <hr />} {show && <ChatRoom roomId={roomId}/>} </> ); }// Chat.js . export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { connect() { console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); }, disconnect() { console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl); } }; }