고차 컴포넌트란?
Higher-order Component (HOC)
즉 컴포넌트 내에서 자주 반복되는 코드를 재사용하기 위한 React 기술
반복되는 코드 찾기
// Post.js
import React, { Component } from 'react';
import axios from 'axios';
class Post extends Component {
state = {
data: null
}
async initialize() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
this.setState({
data: response.data
});
} catch (e) {
console.log(e);
}
}
componentDidMount() {
this.initialize();
}
render() {
const { data } = this.state;
if (!data) return null;
return (
<div>
{ JSON.stringify(data) }
</div>
);
}
}
export default Post;
// Comments.js
import React, { Component } from 'react';
import axios from 'axios';
class Comments extends Component {
state = {
data: null
}
async initialize() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/comments?postId=1');
this.setState({
data: response.data
});
} catch (e) {
console.log(e);
}
}
componentDidMount() {
this.initialize();
}
render() {
const { data } = this.state;
if (!data) return null;
return (
<div>
{JSON.stringify(data)}
</div>
);
}
}
export default Comments;
여러 컴포넌트에서 동일한 코드가 반복된다면, 반복되는 코드를 찾아 HOC를 만든다.
HOC 만들기
*원본 컴포넌트를 변환하지마세요. 구성을 사용하세요.
고차 컴포넌트는 컴포넌트에 기능을 추가합니다. 고차 컴포넌트는 맺음을 과감하게 변경해서는 안됩니다. 고차 컴포넌트는 반환된 컴포넌트에서는 래핑된 컴포넌트와 비슷한 인터페이스가 있어야합니다.
고차 컴포넌트는 특정 관심사과 관련이 없는 props를 통해야합니다. 대부분의 고차 컴포넌트에는 다음과 같은 렌더링 메서드가 포함되어있습니다.
import React, { Component } from 'react';
import axios from 'axios';
const withRequest = (url) => (WrappedComponen) => {
return class extends Component {
state = {
data: null
}
async initialize() {
try {
const response = await axios.get(url);
this.setState({
data: response.data
});
} catch (e) {
console.log(e);
}
}
componentDidMount() {
this.initialize();
}
render() {
const { data } = this.state;
return (
<WrappedComponent {...this.props} data={data}/>
)
}
}
}
export default withRequest;
HOC 사용하기
import React, { Component } from 'react';
import withRequest from './withRequest';
class Post extends Component {
render() {
const { data } = this.props;
if (!data) return null;
return (
<div>
{ JSON.stringify(this.props.data) }
</div>
);
}
}
주의사항
*render 메서드 안에서 고차 컴포넌트를 사용하지마세요.
React의 비교 알고리즘은 컴포넌트 ID를 사용하여 기존 서브트리를 업데이트 해야 하는지 아니면 버리고 새로운 노드를 마운트해야 하는지를 결정합니다. render 에서 반환된 컴포넌트가 이전 렌더링의 컴포넌트와 동일하다면(===) React가 새 트리와 비교하여 반복적으로 서브트리를 업데이트합니다. 만약 동일하지 않다면 이전 서브트리는 완전히 마운트 해제됩니다.
*정적 메서드는 복사해야합니다.
고차 컴포넌트를 컴포넌트에 적용할 때 원본 컴포넌트는 컨테이너 컴포넌트에 감싸집니다. 즉 새 컴포넌트에는 원본 컴포넌트의 정적 메서드가 없습니다.
// Define a static method
WrappedComponent.staticMethod = function() {/*...*/}
// Now apply a HOC
const EnhancedComponent = enhance(WrappedComponent);
// The enhanced component has no static method
typeof EnhancedComponent.staticMethod === 'undefined' // true
이 문제를 해결하기 위해 메서드를 반환하기 전에 컨테이너에 메서드를 복사할 수 있습니다.
function enhance(WrappedComponent) {
class Enhance extends React.Component {/*...*/}
// Must know exactly which method(s) to copy :(
Enhance.staticMethod = WrappedComponent.staticMethod;
return Enhance;
}
다른 긍정적인 해결방법은 정적 메서드를 컴포넌트 자체와 별도로 내보내는 것입니다.
// Instead of...
MyComponent.someFunction = someFunction;
export default MyComponent;
// ...export the method separately...
export { someFunction };
// ...and in the consuming module, import both
import MyComponent, { someFunction } from './MyComponent.js';
*Refs는 전달할 수 없습니다.
고차 컴포넌트에 대한 컨벤션은 모든 props를 래핑된 컴포넌트로 전달하는 것이지만 refs를 전달하는 것은 불가능합니다. 이 이유는 ref 가 prop이 아니기 때문입니다. key 처럼 React가 특별히 처리합니다. 컴포넌트가 고차 컴포넌트의 결과인 요소에 대한 ref를 추가하면 ref는 래핑된 컴포넌트가 아닌 가장 바깥쪽 컨테이너 컴포넌트의 인스턴스를 참조합니다.
reactjs-kr.firebaseapp.com/docs/higher-order-components.html
'React' 카테고리의 다른 글
[React 스터디] 7 : 다른 라이브러리와 통합하기 (0) | 2020.10.12 |
---|---|
SVG 파일을 컴포넌트로 만들기 (0) | 2020.10.06 |
useState를 사용한 배열 set (0) | 2020.09.22 |
객체를 사용한 style 작성 (0) | 2020.09.22 |
[React 스터디] 5 : Ref 전달하기 (0) | 2020.09.20 |
댓글