[HOC]Higher Order Conponent

yoosg·2020년 5월 2일

HOC는 자바스크립트의 HOF(Higher Order Function와 비슷하며 F(Function) 대신 C(Component)를 리턴 하는 것이다. HOC는 리액트 컴포넌트를 인자로 받아서 새로운 리액트 컴포넌트를 리턴하는 함수다.

Basic Component

Comments.js

import React, { useState, useEffect } from 'react';
import Axios from 'axios';

const Comments = () => {
  const [data, setData] = useState(null);
  useEffect(() => {
    async function fetchAPI() {
      try {
        const res = await Axios.get(
          'https://jsonplaceholder.typicode.com/comments?postId=1'
        );
        setData(res);
      } catch (e) {
        console.log(e);
      }
    }
    fetchAPI();
  }, []);
  return <div>{JSON.stringify(data)}</div>;
};
export default Comments;

Post.js

import React, { useState, useEffect } from 'react';
import Axios from 'axios';

const Post = () => {
  const [data, setData] = useState(null);
  useEffect(() => {
    async function fetchAPI() {
      try {
        const res = await Axios.get(
          'https:jsonplaceholder.typicode.com/posts/1'
        );
        setData(res);
      } catch (e) {
        console.log(e);
      }
    }
    fetchAPI();
  }, []);
  return <div>{JSON.stringify(data)}</div>;
};
export default Post;
  • 특정 주소에 GET 요청을 날린다.
  • 결과물을 state 의 data 안에 담는다.
  • 해당 data 를 JSON 형태 그대로 렌더링을 해준다.

요청하는 주소와 컴포넌트의 이름만 다를 뿐 똑같은 기능을 하고있다. HOC를 활용해 중복되는 코드를 줄여보자.

Higher Order Component

반복되는 코드를 줄이기 위해서 컴포넌트를 리턴하는 HOC를 작성해 사용하고 HOC의 네이밍은 with____형식으로 해준다.

HOC의 동작을 간단하게 나타내면 다음과 같다.

// HOC
const HOC = ReactComponent => EnhancedReactComponent;

// Component
export default HOC(ReactComponent);

// react-redux에서 제공하는 connect 함수도 HOC다
export default connect(mapStateToProps, mapDispatchToProps)(ReactComponent); 
  • 컴포넌트를 파라미터로 받아온다.
  • 함수 내부에서 새 컴포넌트를 만든다.
  • 해당 컴포넌트 안에서 파라미터로 받아온 컴포넌트를 렌더링한다.
  • 받아온 props 들은 그대로 파라미터로 받은 컴포넌트에게 다시 넘겨준다.
  • 필요에 따라 추가 props 도 넘겨준다.

withRequest.js

import React, { useState, useEffect } from 'react';
import Axios from 'axios';

const withRequest = (url) => (WrappedComponent) => {
  return (props) => {
    const [data, setData] = useState(null);
    useEffect(() => {
      async function initialize() {
        try {
          const res = await Axios.get(url);
          setData(res);
        } catch (e) {
          console.log(e);
        }
      }
      initialize();
    }, []);
    return <WrappedComponent data={data} />;
  };
};
export default withRequest;

(url, WrappedComponent) 형태가 아닌 (url) => (WrappedComponent) curring function 형태로 확장성을 고려 할 수 있다.

  • 동작 추상화
  • 여러가지 HOC를 사용

Comments.js

import React from 'react';
import withRequest from './withRequest';

const Comments = (props) => {
  const { data } = props;
  if (!data) return null;
  return <div>{JSON.stringify(data)}</div>;
};

export default withRequest(
  'https://jsonplaceholder.typicode.com/comments?postId=1'
)(Comments);

Post.js

import React from 'react';
import withRequest from './withRequest';

const Post = (props) => {
  const { data } = props;
  if (!data) return null;
  return <div>{JSON.stringify(data)}</div>;
};

export default withRequest('https:jsonplaceholder.typicode.com/posts/1')(Post);

0개의 댓글