부모 컴포넌트와 자식 컴포넌트를 유연하게 연결할 수 있는 디자인 패턴이다.
이 글을 읽는 독자가 render props pattern, props collection pattern 두가지 패턴을 알고 있다는 가정하에 진행하기 때문에 이 글을 먼저 읽고 오는걸 추천한다.
Props Getter?
부모 컴포넌트가 자식 컴포넌트에게 제공하는 Props를 Getter Function으로 제공하기 때문에 이런 이름이 붙여졌다. 부모의 Props를 Getter를 통해 가져온다.
위 Toggle 컴포넌트는 자식 컴포넌트에게 togglerProps를 제공하고 있다.
하지만, 반대로 자식 컴포넌트가 부모 컴포넌트에게 그 어떤 값도 넘겨 주지 않고 있다. 현 상태의 코드에서는 불가능하다.
그게 가능해지려면, 단순히 부모의 togglerProps라는 객체를 자식이 받아서 사용만 할게 아니라 부모로부터 getTogglerProps라는 함수를 받아서 함수의 매개변수로 자식의 속성들을 전달해주면 된다. 이것이 props getter pattern의 핵심이다.
자식 -> 부모로 어떤 값을 전달해 줄 수 있는 창구를 만들어 주는 것이다.
이렇게 되면, 부모 -> 자식, 자식 -> 부모의 양방향 커뮤니케이션이 가능해지면서도 자식을 언제든지 갈아치울수 있게 유연하게 두 컴포넌트를 결합 시킬 수 있다.
이번에는, 부모에서 내려준 togglerProps객체를 getTogglerProps함수로 변경해보자.
getTogglerProps를 자식에서 실행한다음 spread하기 때문에 부모에서 정의한 onClick 핸들러가 자식에게 부착된다. 그래서 토글 기능은 여전히 똑같이 잘 동작한다.
토글의 원래 기능은 ON과 OFF상태를 변경하는것이다. 원래 토글 컴포넌트의 이 기능을 그대로 놔둔채로 토글 버튼을 눌렀을때 alert을 띄우는 기능을 유연하게 추가해보자.
토글 상태가 OFF -> ON으로 변경된 다음, alert이 잘 뜬다.
우리는 지금 부모의 onClick 이벤트 핸들러와 자식의 onClick 이벤트 핸들러를 유연하게 합성한것이다.
이번에는 자식 컴포넌트에서 onClick핸들러를 부모에 전달해보자.
이제 이 Toggle 컴포넌트를 가져다 사용하는 사람은, 토글 버튼이 눌렸을때 실행하고 싶은 함수를 getTogglerProps의 onClickFromChild에 전달만 해주면 된다. 자식 컴포넌트는 Toggle 컴포넌트 내부의 isOn 상태가 변경되는지 안되는지는 신경쓰지 않아도 된다. 그런점에서 유연하다는것이다.
여기서 조금 더 편하게 쓰도록 약간의 리팩토링을 더해보자.
const compose = (...functions) => (...args) =>functions.forEach((f) => f && f(...args));
위 함수는 자바스크립트의 curring이라는 기법이다. 가장 겉에 있는 함수는 자식 함수를 리턴한다. 이때 이 자식함수에서는 부모 함수에 전달된 매개변수를 클로져를 통해 (…functions)에 접근할 수 있다.
자유변수인 functions를 순회하면서 실행하는것이 전부이다.
그리고 나서 이렇게 부모 컴포넌트(Toggle)의 toggle 함수와 자식 컴포넌트에서 받아온 props.onClickFromChild를 합성해서 onClick함수로 만든다.
그럼 자식에서는 …getTogglerProps()하기만 하면 된다.
그럼 자식에서 버튼이 클릭됬을때 정상적으로 동작한다.
전체코드
https://codesandbox.io/s/restless-microservice-4s9d0?file=/src/App.js:291-437