리액트의 훅(hook)은 클래스 컴포넌트(Class Component)에서 지원하지 않습니다.
그래서 클래스에서 사용할 수 있는 다른 기능들을 제공하는데.....
제공 안되는 기능들이 있습니다.
이럴 때 사용하는 방법이 고차 컴포넌트(HOC, Higher Order Component)입니다.
(참고 : React Docs - 고차 컴포넌트 )
원리는
1) 함수형 컴포넌트(Function Component)를 만들고
2) 필요한 훅을 'props'에 넣도록 구성하고
3) 클래스형 컴포넌트를 감싸서(랩퍼 구현, Wrapped)
4) 'props'를 전달받습니다.
이렇게 구현하면 클래스 컴포넌트에서 사용할 수 없었던
'useNavigate'나 'useLocation'같은 훅들도 사용할 수 있습니다.
이 예제에서는 'useNavigate'와 'useLocation'을 전달합니다.
'WithRouter.js' 파일을 만들고 아래 코드를 넣습니다.
import React, { } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
/**
* 라우터에 대한 HOC 구현
* https://stackoverflow.com/a/73173004/6725889
* @param {any} WrappedComponent
*/
const WithRouter = WrappedComponent => props =>
{
const navigate = useNavigate();
const location = useLocation();
// other hooks
return (
<WrappedComponent
{...props}
{...{ navigate, location }}
/>
);
};
export default WithRouter;
11번 줄 : 원하는 훅을 선언합니다.
18번 줄 : 'props'에 전달할 훅들을 나열합니다.
이제 클래스 컴포넌트를 다음과 같이 구성합니다.
import React, { Component, } from 'react';
import WithRouter from './WithRouter.js';
class Test extends Component
{
constructor(props)
{
super(props);
console.log("navigate : " + this.props.navigate);
console.log("location : " + this.props.location);
}
render()
{
return
{
<div></div>
}
}
}
export default WithRouter(Test);
2번 줄 : 위에서 만든 'WithRouter.js' 파일의 위치를 지정합니다.
23번 줄 : 사용하려는 클래스를 래퍼로 감싸줍니다.
'Test' 컴포넌트를 '<BrowserRouter></BrowserRouter>'안에서 렌더링하면 다음과 같이 로그가 찍힙니다.
참고 : stackoverflow - How to use useNavigate( ) React-Router-Dom Hook in Class Component - Drew Reese님 답변
이렇게 변태적인 모양이 된 건 리액트의 구조 때문이라고 하는데....
그냥 클래스 컴포넌트에 대한 훅 구현체를 'React.Component'에 만들어주면 되는 거 아닌가.....?
거기다 이 기능은 일종의 상속이라 클래스 구조랑도 안 맞고.....
리액트 라우터(React Router)를 포기하면 되는 건지 모르겠네요 ㅎㅎㅎ