[HOC]Higher Order Conponent

yoosg·2020년 5월 2일
0

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개의 댓글