HOC는 자바스크립트의 HOF(Higher Order Function와 비슷하며 F(Function) 대신 C(Component)를 리턴 하는 것이다. HOC는 리액트 컴포넌트를 인자로 받아서 새로운 리액트 컴포넌트를 리턴하는 함수다.
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;
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;
요청하는 주소와 컴포넌트의 이름만 다를 뿐 똑같은 기능을 하고있다. HOC를 활용해 중복되는 코드를 줄여보자.
반복되는 코드를 줄이기 위해서 컴포넌트를 리턴하는 HOC를 작성해 사용하고 HOC의 네이밍은 with____
형식으로 해준다.
HOC의 동작을 간단하게 나타내면 다음과 같다.
// HOC
const HOC = ReactComponent => EnhancedReactComponent;
// Component
export default HOC(ReactComponent);
// react-redux에서 제공하는 connect 함수도 HOC다
export default connect(mapStateToProps, mapDispatchToProps)(ReactComponent);
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 형태로 확장성을 고려 할 수 있다.
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);
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);