소켓에서 데이터를받은 후 useEffect ()가 내 로컬 상태를 재설정하는 것처럼 보이는 이유는 무엇입니까?

drice89

SocketIO를 통해 메시지를 보내고받는 간단한 반응 구성 요소가 있습니다. 내 상태 후크는 다음과 같습니다.

 const [newMessage, createMessage] = useState('');
 const [messages, setMessage] = useState([]);
 const [isConnected, setConnection] = useState(false);

아이디어는 사용자가 소켓을 통해 메시지를 작성하고 보낼 수 있고 메시지를 다시받을 수 있다는 것입니다. 사용자가 텍스트 영역에 텍스트를 입력합니다. 메시지의 내용은 "newMessage"로컬 상태 변수 (필요한 경우 아래 구현 세부 정보)에 저장되고 사용자는 소켓을 통해 newMessage를 보냅니다.

const sendMessage = () => {
    const currentMessage = {...newMessage}; //reduced for the sake of brevity

    socket.emit('message', currentMessage);
    createMessage('');
  };


const composeMessage = (
    <>
      <div>
        <textarea rows="2" cols="28" placeholder="Chat Message" onKeyDown={(e) => handleKeyDown(e)} onChange={(e) => createMessage(e.currentTarget.value)} value={newMessage} />
      </div>
      <div>
        <button onClick={sendMessage}><i className="ra ra-horn-call" /></button>
      </div>
    </>
  );

서버 측에서는 메시지가 수신되고 즉시 회의실로 다시 전송됩니다. 메시지 응답을 수신하는 함수를 useEffect 후크에 넣었습니다. 아이디어는 componentDidMount 대신 후크를 사용하는 것이기 때문에 원래 useEffect의 두 번째 인수로 빈 배열을 전달하여 구현했습니다. 이렇게하면 메시지가 수신 될 때마다 "메시지"상태를 지우고 내용을 새 메시지로 대체하는 것처럼 보입니다. 브라우저에서는 한 번에 상태로 보관할 수있는 메시지가 한 개 뿐인 것처럼 보였습니다. 이전 메시지는 계속 교체되었습니다. 두 번째 인수 배열에서 "메시지"상태를 전달하는 데 지 쳤고 메시지가 상태에 추가되는 것처럼 보였고 구성 요소가 수신 될 때 다시 렌더링되었습니다.

나는 모든 후속 메시지에서 성능 문제가 있음을 발견했으며 궁극적으로 소켓 리스너가 각 렌더링에 다시 적용된다는 것을 발견했습니다. 이를 막기 위해 동료는 내가 다시 렌더링 할 때마다 소켓이 다시 추가되는 것을 방지하는 부울을 상태에 추가 할 것을 제안했습니다. 구성 요소를 업데이트했고 결과는 메시지 상태를 두 번째 인수로 전달하지 않았을 때 처음과 동일했습니다. 상태의 첫 번째 메시지를 계속 교체하고 새 메시지를 추가하지 않았습니다. 리스너가 로컬 상태를 업데이트하고 소켓을 통해 새 메시지가 올 때마다 메시지를 다시 렌더링하기를 원합니다. 나는 후크로 이것을하는 방법에 대해 약간의 손실을 입었습니다. 누구나 아이디어가 있습니까?

내가 작성한 useEffect 후크의 마지막 반복은 다음과 같습니다.

  useEffect(() => {
    debugger
    if (!isConnected) {
      socket.on('message', (message) => {
        const nextState = messages.slice();
        nextState.push(message);
        setMessage(nextState);
        debugger
      });
      setConnection(true);
    }
  }, [messages, setConnection]);
Weiklr

귀하의 코드에서 useEffect가 실행되고 여러 구독을 만들어 메시지 및 connectionState가 변경 될 때마다 모든 메시지, 각 렌더링에서 수신 대기합니다. 이는 상태가 변경 될 때마다 반응 구성 요소가 렌더링되기 때문입니다. 웹 소켓 연결 및 리스너는 부작용으로 간주 될 수 있으므로 컴포넌트가 마운트 해제 될 때이를 처리하기 위해 리턴 콜백을 구현해야합니다.

모든 웹 소켓 처리 및 채팅 메시지 논리가 단일 반응 구성 요소 내에 있다고 가정하면 웹 소켓 연결 및 리스너를 마운트시 한 번만 생성하고 마운트 해제를 처리하기위한 리턴 호출을 제공하면됩니다. 페이지 새로 고침을 수행하거나 구성 요소가 다시 렌더링을 트리거 할 수있는 상위 상태에 의존합니다.

 useEffect(() => {
            socket.connect();
            socket.on('connect', () => {
                console.log('socket connected:', socket.connected);
            });
            socket.on('message',...);
        }
        return () => {
            console.log('websocket unmounting!!!!!');
            socket.off();
            socket.disconnect();

        };
    }, []);

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관