next.js 에서 레이아웃이 hoc 소스 발견. 파다파다 보니까 결국 컴포넌트 패턴에 다다름. 함수 컴포지션까지 싹 공부함. 이해하니까 좋네. 근데 머리가 아파.
컴포넌트에 상태가 있을 수도 없을 수도 있다. 하지만 상태를 가지는 컴포넌트보다는 상태 없는 컴포넌트가 재사용성이 높다. 상태는 외부에서 제공하면 되거든.
컨테이너 x 프레젠테이셔녈 패턴이라고도 불리운다.
바보는 아무것(상태)도 모른다. 오직 UI 만 안다.
const 사용자목록 = 외부상태매개변수 =>
<ul>
{외부상태매개변수.사용자들.map( 한명 => (
<li>{한명.이름}은 - {한명.나이} 살이다</li>
))}
</ul>
똑똑이는 (상태를)알고 기억하고 추적한다.
const 사용자목록_컨테이너 = () => {
const fetch결과 = fetch사용자들();
return ({
<사용자목록 사용자들={fetch결과}
})
}
추상화, 추상화를 통해서 어떤 컴포넌트를 받던 같은 결과 컴포넌트를 반환하는 함수를 고차 컴포넌트라고 한다.
구체적으로는 추후에 props를 받을 컨테이너 컴포넌트를 반환한다고 보면 될 거 같다.
export default ComposedComponent => {
// 컨테이너 된, Wrrapped 된 컴포넌트 반환
return props => <ComposedComponent {...props} />;
};
함수형을 이해하기 어려운 게 묶어서 사고하는 거. 수포자였던 나에게는 넘 어려운 이야기. 그래서 한번 파보고 옴: 커리와 함수합성 그리고 point-free 관점
함수 합성
x. f. z = x(f(z(인자))
세 함수형 컴포넌트 합성해보자.
showProp
export default props => (
<p>{props}<p>
);
const showProps = x => x +1
withLayout
export default ComposedComponent => {
props => (
<div>
<ComposedComponent {...props} />
</div>
);
// 헷갈리는 포인트. 커리된 함수라 인자를 추후에 받음
const withLayout = funcX => props => funcX(prop)*2
withData
export default ComposedComponent => {
// withLayout 이 wrapped
return props => <ComposedComponent {...props} />;
};
// 헷갈리는 포인트. 커리된 함수라 인자를 추후에 받음
const withLayout = funcY => props => funcY(prop)/4
오렇게 쓰는거고. 어쨌건 withData 가 props 를 받으니. withData 에서 주입된 prop 을 withLayout prop 에 넣고, 그렇게 주입된 prop 을 showProp 까지 주르륵 넣어주는 거.
const showProps = x => x +1
const withLayout = funcX => props => funcX(prop)*2
const withData = funcY => props => funcY(prop)/4
위 함수를 합성해보면 아래와 같이 나옴.
widhDate(withLayout(showProp)))
1. withLayout(showProp)
withLayout(funcX) = props => funcX(prop)*2
2. widhData(withLayout(showProp))
withLayout(funcY) = props => funcY(prop)/4
= props => funcY(funcX(props+1)*2)/4)
= funcY(funcX(props+1)*2)/4)(props)
= ((props+1)*2)/4)(props)
즉, 처음 함수에 넣은 인자에 한가지 연산만 반복적으로 하는 것.
widhDate(withLayout(showProp)))(데이터)
기호만으로 이해하는 게 어렵다. 그럼 언어로 이해해보자.
인자를 받아서 합정 대상 함수에 전달,그래야 합성대상 함수 결과를 사용가능
const withData = funcY => x => funcY(x)/4
인자를 받아서 합정 대상 함수에 전달, 그래야 합성대상 함수 결과를 사용가능
const funcY = funcX => x => funcX(x)*2 // (funcX(x)*2)(x)
첫 합성 대상에서 인자를 전달 받아서 계산
const funcX = x => x +1
이제 계산이 시작됨.
funcY(자료)
= funcX(자료)*Y계산
= (func(자료)*X계산)*Y계산
= ((자료계산)X계산)Y계산)
//
((props=> x+1)(props))*2
(((props=> x+1))*2)(props))/4
((((props=> x+1))*2))/4)(props)
대체 왜 인자를 대상함수에 넘겨주는 거야?
withData 는 인자를 받아서 showProps 에 넘겨줌.
왜냐면 showProps 계산이 되어야 연쇄적으로 계산을 할 거 아냐?
withData(widhLayout(showProps))(인자)
결국 필요에 의한 거네. decomposition 을 해야 composition 할 수 있는데 decomposition 자체가 어렵고 생소하다.
요걸 redux compose 로도 표현할 수 있음
import { compose } from 'redux';
const 합성된컴포넌트 = compose(widhDate, widhLayout, showProp)
export default 합성된 컴포넌트
다른 컴포넌트에서 요거 사용.
return <합성된 컴포넌트 {...props} />