리액트 훅 + WebSockets의 올바른 사용 방법
WebSockets 서버에 연결하여 메시지를 기록해야 합니다.React 클래스 컴포넌트를 사용하여 이 논리를 삽입합니다.componentDidMount
라이프 사이클 훅을 사용하여 즐겁게 이행할 수 있지만, 어떻게 훅을 사용하여 적절히 구현해야 할지 잘 모르겠습니다.
제 첫 번째 시도는 이렇습니다.
import React, {useEffect} from 'react';
export default function AppWs() {
useEffect(() => {
let ws = new WebSocket('wss://ws.kraken.com/');
ws.onopen = () => console.log('ws opened');
ws.onclose = () => console.log('ws closed');
ws.onmessage = e => {
const message = JSON.parse(e.data);
console.log('e', message);
};
return () => {
ws.close();
}
}, []);
return (
<div>hooks + ws</div>
)
}
에 접속 및 로그 로직을 추가했습니다.useEffect
의존관계가 있는 빈 어레이가 제공되어 모든 것이 정상적으로 동작했습니다.추가가 필요할 때까지pause
로깅을 일시 정지합니다.
export default function AppWs() {
const [isPaused, setPause] = useState(false);
useEffect(() => {
let ws = new WebSocket('wss://ws.kraken.com/');
ws.onopen = () => console.log('ws opened');
ws.onclose = () => console.log('ws closed');
ws.onmessage = e => {
if (isPaused) return;
const message = JSON.parse(e.data);
console.log('e', message);
};
return () => {
ws.close();
}
}, []);
return (
<div>
<button onClick={() => setPause(!isPaused)}>{isPaused ? 'Resume' : 'Pause'}</button>
</div>
)
}
ESLint가 나한테 소리를 지르기 시작했는데isPaused
의존 관계로서 진술하다useEffect
.
음, 그래, 됐어.
그러나 버튼을 클릭할 때마다 WS 서버에 재접속되어 있는 것을 알 수 있었습니다.이건 분명히 내가 원하는게 아니야.
내 다음 반복은 두 개를 사용하는 것이었다.useEffect
s: 1개는 접속용, 1개는 메시지 처리용.
export default function AppWs() {
const [isPaused, setPause] = useState(false);
const [ws, setWs] = useState(null);
useEffect(() => {
const wsClient = new WebSocket('wss://ws.kraken.com/');
wsClient.onopen = () => {
console.log('ws opened');
setWs(wsClient);
};
wsClient.onclose = () => console.log('ws closed');
return () => {
wsClient.close();
}
}, []);
useEffect(() => {
if (!ws) return;
ws.onmessage = e => {
if (isPaused) return;
const message = JSON.parse(e.data);
console.log('e', message);
};
}, [isPaused, ws]);
return (
<div>
<button onClick={() => setPause(!isPaused)}>{isPaused ? 'Resume' : 'Pause'}</button>
</div>
)
}
이것은 예상대로 동작합니다만, 뭔가 놓치고 있는 것 같은 느낌이 들고, 이 태스크는 1개로 간단하게 해결할 수 있습니다.useEffect
리액트 훅을 올바르게 사용하고 있는지 확인할 수 있도록 코드를 리팩터링 해 주세요.감사합니다!
웹 소켓을 한 번만 설정하기 때문에 상태가 아닌 ref를 사용하는 것이 더 좋다고 생각합니다.
순서useEffect
중요합니다.
George가 댓글로 제시한 것처럼 첫 번째,useEffect
ws.current
변수에 저장되기 때문에close
같은 인스턴스를 가리킵니다.
export default function AppWs() {
const [isPaused, setPause] = useState(false);
const ws = useRef(null);
useEffect(() => {
ws.current = new WebSocket("wss://ws.kraken.com/");
ws.current.onopen = () => console.log("ws opened");
ws.current.onclose = () => console.log("ws closed");
const wsCurrent = ws.current;
return () => {
wsCurrent.close();
};
}, []);
useEffect(() => {
if (!ws.current) return;
ws.current.onmessage = e => {
if (isPaused) return;
const message = JSON.parse(e.data);
console.log("e", message);
};
}, [isPaused]);
return (
<div>
<button onClick={() => setPause(!isPaused)}>
{isPaused ? "Resume" : "Pause"}
</button>
</div>
);
}
useEffect(() => {
const socket = new WebSocket('wss://ws.kraken.com');
socket.addEventListener('message', function (event) {
const a = JSON.parse(event.data);
setPriceWebSocket(a);
const amin = socket.send(
JSON.stringify({
event: 'subscribe',
pair: ['XBT/USD', 'XBT/EUR', 'ADA/USD'],
subscription: { name: 'ticker' },
}),
);
});
언급URL : https://stackoverflow.com/questions/60152922/proper-way-of-using-react-hooks-websockets
'source' 카테고리의 다른 글
여러 열을 여러 변수로 선택 (0) | 2023.03.27 |
---|---|
WordPress에서 검색 쿼리와 일치하는 게시물을 프로그래밍 방식으로 가져오는 방법은 무엇입니까? (0) | 2023.03.27 |
절약, HTTP RPC(JSON+gzip)가 아닌 이유 (0) | 2023.03.27 |
Reacjs 프로젝트 구축 후 불투명도 값이 1%로 변경됨 (0) | 2023.03.27 |
IntelliJ IDEA에서 1개의 실행 Configuration으로 여러 Spring Boot 어플리케이션을 실행하는 방법이 있습니까? (0) | 2023.03.27 |