
에러가 발생할 경우 에러메시지를 Toast로 띄우는 로직이다.
QueryProvider.tsx
const { open } = useModal({ delay: 2000 });
queryClient.setDefaultOptions({
// ..
mutations: {
onError: (error) => {
const errorMessage = error ?? '오류가 발생했습니다. 다시 시도해주세요.';
open(() => <Toast>{errorMessage}</Toast>);
},
},
});
Toast.tsx
export default function Toast({ children }: StrictPropsWithChildren) {
// ..
}
open(() => <Toast>오류가 발생했습니다. 다시 시도해주세요.</Toast>);에서는 에러가 발생하지 않았다. 같은 문자열인데 왜 이 방법은 에러가 발생하지 않은 것일까?
<Toast>{errorMessage}</Toast> 🚫
위와 같은 방식으로 할 경우, children으로 넘기는 값이 문자열이기에 에러가 발생할만 하다.
<Toast>오류가 발생했습니다. 다시 시도해주세요.</Toast> ✅
그런데 위 방식은 에러가 발생한 것일까. 그냥 문자열을 넘기면 React에서는 ReactNode로 인식하는 것일까?
<Toast><p>오류가 발생했습니다. 다시 시도해주세요.<p/></Toast> 🚫
위 방식은 에러가 발생한다.
<Toast><>오류가 발생했습니다. 다시 시도해주세요.</></Toast> ✅
이 방식은 type 에러가 발생하지 않고, lint에러만 뜬다.
package.json에 다음과 같은 코드를 추가하여 @types/react 버전을 17로 고정한다.
"resolutions": {
"@types/react": "^17.0.38"
},
<>로 감싼다
<Toast>
<>{errorMessage}</>
</Toast>
props로 값을 넘긴다.
open(() => <Toast message={errorMessage}></Toast>);
react18업데이트 이후 type적용이 일부 불안정한 부분이 있었다고 한다. 그래서, react17로 type버전을 낮추니 해결이 되었던 것이다. 타입을 17로 낮추는 것은 다른 코드에 상당히 사이드 이팩트가 있을 수 있을 것이라 판단하였다. 결국<>로 감싸는 방식으로 결정했다.