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