의존성배열에 있는 값이 바뀌면 useEffect를 재실행 함.
이때 의존성 배열에 있는 값이 객체라면 말이 달라진다.
객체를 사용할땐 최대한 특정 프로퍼티만 사용하거나, useEffect내부에서 만들어서 사용하자.
참조형 데이터는 비교할때 조심해서 다루자!
브라우저에서 지원하는 EventSource는 헤더에 토큰이 실리지 않아, 그 기능을 지원하는 EventSourcePolyfiill이라는 라이브러리를 사용했다.
이후 구현을 하면서, 특정 이벤트에 대해 핸들러를 부착해야했음.
const sse = new EventSourcePolyfill(url);
sse.addEventListener('myEvent', handler);
하지만 타입오류 발생.
왜 그런지 하고 구현체를 보니...
interface EventSourceEventMap {
"error": Event;
"message": MessageEvent;
"open": Event;
}
addEventListener<K extends keyof EventSourceEventMap>(
type: K,
listener: (this: EventSource, ev: EventSourceEventMap[K]) => any,
options?: any,
): void;
즉, EventSourceEventMap
에는 myEvent
가 없다. 따라서 타입 에러가 남.
아래처럼 제네릭으로 전달하려고 하여도, keyof
라는 제약조건때문에 불가능.
addEventListener<{ 'myEvent': MessageEvent }>....
어떻게 할까?
타입을 수정할순 있다.
interface EventSourceEventMap {
"error": Event;
"message": MessageEvent;
"open": Event;
"myEvent": MessageEvent;
}
그러나 라이브러리를 다시 설치하면 날아간다.
잘 찾아보니 addEventListener
의 타입이 하나 더 있었다.
interface EventListenerObject {
handleEvent(evt: Event): void;
}
interface EventListener {
(evt: Event): void;
}
type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: any): void;
오! type
이 제약조건을 만족하지 않아도 된다.
하지만, MessageEvent
를 받을 순 없다...😥
그래서 결국!
const handleInitConnect = (e: Event) => {
const messageEvent = e as MessageEvent;
const data = JSON.parse(messageEvent.data);
setData(data);
};
위처럼 Event
인척하고 받아와서 as
키워드를 이용하여 MessageEvent
로 컴파일러에게 이벤트 타입을 명시해주었다.
이게 맞나 싶지만, 일단 문제 해결. as
키워드를 쓰지 않고 할 수 있는 방향을 찾아봐야겠다.
라이브러리 타입 수정한 뒤, 다른 패키지 설치하려고 yarn add ...
썼을때 나온 문제!
yarn cache clean --all
로 캐시 날리고 설치하니 해결