400,403,404 ... 늘어나는 애러에 대응
최하단 자식컴포넌트의 애러는 모든 화면의 애러로 표현되어 한다.
잘못된 url, 404 애러 ( 혹은 커스텀 페이지 )
올바른 url 이지만, 리소스가 없는 경우 404 애러
올바른 url 이지만, 서버응답에 문제가 생긴경우 400,500 등 애러
초기 상태
----- toplevel [ 애러없음 -> router 랜더링 ]
-- router/switch/route/
-- children1
-- children2
-- children3
-- children4
깊은 하위 컴포넌트에서 애러발생한 경우
----- toplevel [ 애러없음 -> router 랜더링 ]
-- router/switch/route/
-- children1
-- children2
-- children3
-- children4 -> API 404 애러 !
ErrorHandler는 마치 미들웨어 같다.
import React from "react";
import { useHistory } from "react-router-dom";
import { atom, useRecoilState } from "recoil";
import Page404 from "../components/error-page/Page404";
import Page403 from "../components/error-page/Page403";
import Page400 from "../components/error-page/Page400";
import Page500 from "../components/error-page/Page500";
// 애러 state를 가지고 있는 atom
interface IErrorStatus {
isError: boolean;
errorCode: "400" | "403" | "404" | "500" | "unknown" | null;
}
const atomErrorStatus = atom<IErrorStatus>({
key: "ErrorStatus",
default: {
isError: false,
errorCode: null,
},
});
// atom 애러 state에 의해 error페이지를
// 랜더링하는 render props
const ErrorHandler: React.FC<{}> = ({ children }) => {
const history = useHistory();
const [errorStatus, setErrorStatus] = useRecoilState(atomErrorStatus);
React.useEffect(() => {
const unlisten = history.listen(() =>
setErrorStatus(() => ({ errorCode: null, isError: false }))
);
return unlisten;
}, [history, setErrorStatus]);
const renderContent = () => {
if (errorStatus.errorCode === "400") return <Page400 />;
if (errorStatus.errorCode === "403") return <Page403 />;
if (errorStatus.errorCode === "404") return <Page404 />;
if (errorStatus.errorCode === "500") return <Page500 />;
if (errorStatus.isError) return <Page400 />;
return children;
};
return <div>{renderContent()}</div>;
};
export { ErrorHandler, atomErrorStatus };
ErrorHandler 컴포넌트 의 children은 애러가 없다면 랜더링이 될 것이다.
import React from "react";
import Test from "components/Test";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import LandingPage from "../pages/common/landing-page";
import { TakersHome } from "../pages/takers/layout/TakerMain";
import { MakersHome } from "../pages/makers/layout/MakerMain";
import { ErrorHandler } from "states/recoil/error-state";
import Page404 from "./error-page/Page404";
const Router = () => {
return (
<BrowserRouter>
<ErrorHandler>
<Switch>
<Route path="/" exact component={LandingPage} />
<Route path="/takers" component={TakersHome} />
<Route path="/makers" component={MakersHome} />
<Route path="/test" component={Test} />
<Route component={Page404} />
{/* <Redirect from="*" to="/" /> */}
</Switch>
</ErrorHandler>
</BrowserRouter>
);
};
export default Router;
지역 컴포넌트에서 애러가 발생하면 전역상태관리도구인 Recoil에게 이를 알린다.
import React from "react";
import { useRecoilState } from "recoil";
import { atomErrorStatus } from "recoil/error-state";
const StrategySearchC = () => {
const [errorStatus, setErrorStatus] = useRecoilState(atomErrorStatus);
setErrorStatus((p) => ({
isError: true,
errorCode: "404",
}));
return <div>StrategySearch!</div>;
};
export default StrategySearchC;