useReducer
사용 시에, dispatch
의 타입이 자꾸 오류를 발생시켰다.find
, filter
함수 사용 시, 리턴 값에서 undefined
를 포함할 수 있음에 따라 타입 에러를 발생시켰다.context
에 state와 reducer를 포함해서 넘겨주려고 하니, 자꾸 리듀서의 타입에 대해서 에러가 무한히 발생하는 것이다. 리듀서 자체는 (state, action) => state
의 형태를 가지고 있는데, 이를 useReducer의 dispatch 함수로 넣어주면 자꾸 타입이 Dispatch<any>
가 되어 에러가 났다. Dispatch
는 (action) => void
의 형태를 갖는다.
(사진을 좀 찍어놓을 걸 고치는데 급급해서...)
Flux 패턴 으로 검색을 하면 100개의 블로그 중에 99개가 이 사진을 쓴다.
정도가 flux의 기본적인 동작 방식이라고 할 수 있다.
따라서, dispatcher는 사용자의 동작을 포착해서 리듀서에게 수행할 것을 지시하는 역할이다.
const [chatroomContext, chatroomListDispatch] = useReducer(
chatroomListReducer,
CHATTINGS
);
보통 useReducer
는 이런 패턴으로 선언하는데, 나는 그동안 이러한 선언 형태 때문에 리듀서가 곧 dispatcher구나...! 라고 잘못 이해하고 있었다 (남탓하기)
따라서 dispatch
함수 자체에는 어떠한 리턴값이 존재하지 않는다.
export const ChatroomContext = createContext<{
chatroomContext: chatroomList;
chatroomListDispatch: Dispatch<chatroomAction>;
}>({
chatroomContext: CHATTINGS,
chatroomListDispatch: () => null,
});
context를 다룰 custom hook을 만드는 과정에서, 배열중 한개의 원소를 찾기 위해 filter
를 썼었다. 근데 filter
는 조건에 만족하는 모든 원소들을 배열의 형태로 가지기 때문에 객체 형태의 타입을 리턴한다고 명시했다가 계속해서 에러가 나는 것이었다.
왠지 저번에도 겪은 에러라서 처음에는 끝에 [0]을 붙여서 해결해보았다. 하지만 뭔가 간지가 안나니까,,, find
를 사용해서 써 봤는데 그때는 또,,,
흠... 로직 상 undefined
일 수 없으나, find
함수의 특성상 그럴 수 있기 때문에 이러한 에러가 발생하는 것 같다.
타입스크립트에서 이런 경우에, 해당 값이 non-null
하다고 단언하는 방법이 있다. non-null assertion operator
를 사용하는 방법이 있는데, 무언가 nullable한 값 뒤에 !
를 붙여주면 된다.
const getSingleChatroom = (friendId: number): chatroom => {
return chatroomContext.find((chatroom) =>
chatroom.friendId === friendId)!; // 이렇게
};
그렇다면 무조건 non-null
한 값을 가지는 걸로 타입스크립트가 인식하게 된다.