Search
Duplicate

[React] react-router useNavigate의 wrapper component 뜯어보기

간단소개
react-router의 컴포넌트를 뜯어보자
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
React
TypeScript
Scrap
태그
9 more properties
react-router에는 hook과 동일한 동작을 하는 component들이 존재한다. 예를들어 useNavigate라는 훅이 있으면 Navigate라는 컴포넌트도 정의되어 있는 것이다.

Navigate코드보기

코드를 살펴보면 상당히 간단하게 되어 있는 것을 알 수 있다. invariant와 waring은 에러를 처리하는 부분이니 넘어가면 useNavigate 훅을 받아서 useEffect에서 해당 훅을 실행하는 것을 확인할 수 있다.
아래 useNavigate코드를 보면 알 수 있듯이 NavigateFunction 타입이 To와 NavigationOptions를 받는것을 알 수 있다. 여기서 NavigationOptions가 replace와 state를 옵셔널로 가지는 타입이기 때문에 Navigate컴포넌트에서 replacestate를 prop으로 받아주는 것을 볼 수 있다.
export function Navigate({ to, replace, state }: NavigateProps): null { invariant( useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of // the router loaded. We can help them understand how to avoid that. `<Navigate> may be used only in the context of a <Router> component.` ); warning( !React.useContext(NavigationContext).static, `<Navigate> must not be used on the initial render in a <StaticRouter>. ` + `This is a no-op, but you should modify your code so the <Navigate> is ` + `only ever rendered in response to some user interaction or state change.` ); let navigate = useNavigate(); React.useEffect(() => { navigate(to, { replace, state }); }); return null; }
TypeScript
복사

useNavigate 코드보기

export interface NavigateFunction { (to: To, options?: NavigateOptions): void; (delta: number): void; } export interface NavigateOptions { replace?: boolean; state?: any; } export function useNavigate(): NavigateFunction { invariant( useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the // router loaded. We can help them understand how to avoid that. `useNavigate() may be used only in the context of a <Router> component.` ); let { basename, navigator } = React.useContext(NavigationContext); let { matches } = React.useContext(RouteContext); let { pathname: locationPathname } = useLocation(); let routePathnamesJson = JSON.stringify( matches.map((match) => match.pathnameBase) ); let activeRef = React.useRef(false); React.useEffect(() => { activeRef.current = true; }); let navigate: NavigateFunction = React.useCallback( (to: To | number, options: NavigateOptions = {}) => { warning( activeRef.current, `You should call navigate() in a React.useEffect(), not when ` + `your component is first rendered.` ); if (!activeRef.current) return; if (typeof to === "number") { navigator.go(to); return; } let path = resolveTo( to, JSON.parse(routePathnamesJson), locationPathname ); if (basename !== "/") { path.pathname = joinPaths([basename, path.pathname]); } (!!options.replace ? navigator.replace : navigator.push)( path, options.state ); }, [basename, navigator, routePathnamesJson, locationPathname] ); return navigate; }
TypeScript
복사
이처럼 wrapper component도 결국 hook으로 구현되어 있기 때문에 함수형 컴포넌트 내에서 사용하려면 그냥 hook을 사용하면 될 것 같다. 각각의 상황에 맞게 사용해보자!

reference