2022. 11. 17. 15:30

리액트의 훅(hook)은 클래스 컴포넌트(Class Component)에서 지원하지 않습니다.

그래서 클래스에서 사용할 수 있는 다른 기능들을 제공하는데.....

제공 안되는 기능들이 있습니다.

 

이럴 때 사용하는 방법이 고차 컴포넌트(HOC, Higher Order Component)입니다.

(참고 : React Docs - 고차 컴포넌트 )

 

 

1. 원리

원리는

1) 함수형 컴포넌트(Function Component)를 만들고

2) 필요한 훅을 'props'에 넣도록 구성하고

3) 클래스형 컴포넌트를 감싸서(랩퍼 구현, Wrapped)

4) 'props'를 전달받습니다.

 

이렇게 구현하면 클래스 컴포넌트에서 사용할 수 없었던

'useNavigate'나 'useLocation'같은 훅들도 사용할 수 있습니다.

 

 

2. 랩퍼 구현

이 예제에서는 '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'에 전달할 훅들을 나열합니다.

 

 

3. 사용

이제 클래스 컴포넌트를 다음과 같이 구성합니다.

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)를 포기하면 되는 건지 모르겠네요 ㅎㅎㅎ