리액트 개발자신가요? 당신은 어떻게 로직을 공유하고 있나요?
(???: 커스텀 훅이요!)
당신은 Modal UI를 개발해야하는 프론트 개발자입니다. 이 때 최신 리액트 개발자라면... 모달을 사용하는 컴포넌트에서 사용되는 로직들은 대게 다음과 같이 useModal
스러운 커스텀 훅을 만들어 로직들을 뭉쳐놓고 재사용하게 할 것 같아요.
export const useModal = () => {
const [isShowModal, setIsShowModal] = useState(false);
const openModal = useCallback(() => {
setIsShowModal(true);
}, [setIsShowModal]);
const closeModal = useCallback(() => {
setIsShowModal(false);
}, [setIsShowModal]);
const toggleModal = useCallback(() => {
setIsShowModal(prev => !prev);
}, [setIsShowModal]);
return {isShowModal, openModal, closeModal, toggleModal};
};
(극단적 커스텀 훅 파이기에... 너무나 사랑스러워보인다는..)
하지만 훅이 없던 그 시절이라면 ?! 혹은 리액트가 아닌 바닐라 코드를 짜고 있다면 당신은 어떻게 로직을 공유하게 할 것인가요!? 저는 5가지 방법을 제안하고 싶습니다.
빨간 자동차, 파란 자동차 모두 move
라는 공통 로직을 수행할 수 있어야 합니다. 이 경우 가장 먼저 떠오르는 방법은 확장이 아닐까 싶어요. (YO! 다른 말로는 상속)
class Car {
move() {
console.log("move");
}
}
class RedCar extends Car {
color = "red";
}
class BlueCar extends Car {
color = "blue";
}
const redCar = new RedCar();
const blueCar = new BlueCar();
redCar.move();
blueCar.move();
전화기던 패드던 전화가 될 수 있으면 참 좋겠죠? 다음은 call
기능을 공유하게 해줍니다.
class Callable {
constructor(device) {
this.device = device;
}
call() {
console.log(this.device.name);
}
}
class Phone {
name = "phone";
}
class Pad {
name = "pad";
}
const phone = new Phone();
const pad = new Pad();
const callablePhone = new Callable(phone);
const callablePad = new Callable(pad);
callablePhone.call();
callablePad.call();
log
를 찍는 공통 로직을 컴포넌트에 입혀주고 싶어요! 그렇다면 다음과 같이 로직을 공유하게 할 수 있을 것 같아요!!
import React from "react";
import ReactDOM from "react-dom";
// 1. 단순한 고차함수
const withLog = (Component) => {
return class extends React.Component {
componentDidMount() {
console.log("mount");
}
render() {
return <Component />;
}
};
};
// 2. 발가벗은 컴포넌트
class Component extends React.Component {
render() {
return <div>hi</div>;
}
}
// 3. 고차함수로 인해 옷을 입어버린 고차컴포넌트
const WrappedComponent = withLog(Component);
class App extends React.Component {
render() {
return <WrappedComponent />;
}
}
ReactDOM.render(<App />, document.getElementById("container"));
log
함수를 외부 스코프에 선언, 정의해두고 여러 컴포넌트에서 로그를 찍을 일이 있을 때 사용하게 한다면? 사실상 이 또한 공통 로직을 공유하게 하는 셈이겠죠!! (순수하게 작성해준다면 더욱 좋은 기능 분리가 아닐까 싶어요)
const log = (state) => console.log(state);
class Component extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 10
};
}
componentDidUpdate() {
// 공통 로직을 함수로 분리
log(this.state.data);
}
render() {
return (
<div>
<div>{this.state.data}</div>
<div onClick={() => this.setState({ data: this.state.data + 1 })}>
button
</div>
</div>
);
}
}
class App extends React.Component {
render() {
return <Component />;
}
}
ReactDOM.render(<App />, document.getElementById("container"));
간단해요!! 하위 컴포넌트들에서 공유하는 로직이 있다면 하위 컴포넌트 단에서 이를 작성해줄게 아니라 상위 컴포넌트에서 함수를 만들어 하위 컴포넌트로 뿌려주게 하는거죠!!
import React from "react";
import ReactDOM from "react-dom";
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.props = props;
}
componentDidMount() {
this.props.log("A");
}
render() {
return <div>A</div>;
}
}
class ComponentB extends React.Component {
constructor(props) {
super(props);
this.props = props;
}
componentDidMount() {
this.props.log("B");
}
render() {
return <div>B</div>;
}
}
// 공통 로그 로직을 위에서 만들어 내려준다.
class App extends React.Component {
log(data) {
console.log(data);
}
render() {
return (
<>
<ComponentA log={this.log} />
<ComponentB log={this.log} />
</>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
로직을 공유할 수 있는 5가지 방법에 대해 알아보았어요!! 당신은 공유하는 로직을 하위 컴포넌트 각각 코드를 작성하며 처리하고 있나요? 자세히 바라보면 트레이드 오프가 있겠지만, 한 번쯤은 코드를 되돌아보는 것도 나쁘지 않을 것 같네요 🐸🐸🐸
(유지보수 무한루프에 빠지지 맙시다!)
이 분 저희 회사에서 채용하고 싶은데 갠톡주세요ㅋ