9.3.2 useImperativeHandle을 사용한 실용예제

서문 간단하게 작성해보았습니다!
useImperativeHandle의 실용예제를 살펴보겠습니다. 아래 그림 9-n은 실용예제의 완성본 입니다. 실용예제는 버튼을 클릭하면 css 박스 색상을 변경할 수 있는 어플리케이션 입니다. useImperativeHandle Hook을 사용한 예제와 사용하지 않은 예제를 비교하여 Hook에 대해 더 자세히 다뤄보겠습니다.
 
 
 
 
정연 파트 시작
useImperativeHandle Hook을 사용하여 앞서 만든 실용예제와 같은 어플리케이션을 만들어보겠습니다.
 
function App() { const [open, setOpen] = useState(false); const modalRef = useRef(); return ( <> <button onClick={() => setOpen(true)}>Open</button> <button onClick={() => { //작업내용 }} > Pink Btn </button> <CustomModal ref={modalRef} open={open} onClose={() => setOpen(false)} /> </> ); }
App.js
 
먼저 App.js에서 Open 버튼과 Pink Btn 버튼을 만들었습니다. Open 버튼을 클릭하면 Color Change 모달이 나타나고 Pink Btn 버튼을 클릭하면 color1 텍스트 배경색이 분홍색으로 변경됩니다. 해당 기능을 모달에 해당하는 CustomModal 컴포넌트에서 useImperativeHandle Hook을 활용해 구현하겠습니다. useImperativeHandle Hook을 사용하기 위해 CustomModal 컴포넌트에 modalRef를 props로 전달해주었습니다. 아래 그림 9-n은 Open 버튼을 클릭하여 모달을 띄운 상태입니다.
 
그림 9-2그림 9-2
그림 9-2
 
function CustomModal({ open, onClose }, ref) { const closeRef = useRef(); const pinkRef = useRef(); if (!open) return null; return ( <div> <br /> <button ref={closeRef} onClick={onClose}> &times; </button> <h1>Color Change</h1> <div> <div ref={pinkRef}>color1</div> </div> </div> ); } export default React.forwardRef(CustomModal);
CustomModal.js
 
CustomModal 컴포넌트를 살펴보겠습니다. useRef Hook를 통해 closeRef와 pinkRef 라는 ref 객체를 만듭니다. 두 가지 ref 객체를 각각 모달의 닫기 버튼과 color1 텍스트의 ref 값으로 설정합니다. 이는 닫기 버튼과 color1 텍스트의 DOM을 가르켜 원하는 방식으로 조작하기 위한 목적입니다.
 
useImperativeHandle(ref, () => { return { closeBtn: closeRef.current, pinkBtn: pinkRef.current, }; });
CustomModal.js
 
이후 useImperativeHandle Hook의 인자로 App.js에서 전달해온 props인 ref를 받습니다. 그 다음 콜백함수로 closeBtn과 pinkBtn을 반환하면 상위 컴포넌트인 App.js에서도 해당 객체를 사용할 수 있습니다. closeBtn에 closeRef.current을 할당하여 닫기 버튼 DOM을 가르킬 수 있게 하고, pinkBtn에는 pinkRef.current 을 넣어 ‘color1’ 텍스트의 div 태그를 가르킬 수 있게 합니다. 이를 통해 App.js에서 closeBtn과 pinkBtn을 활용하여 모달 닫기 기능과 배경색 변경 기능을 구현할 기반을 마련했습니다.
 
function CustomModal({ open, onClose }, ref) { const closeRef = useRef(); const pinkRef = useRef(); useImperativeHandle(ref, () => { return { closeBtn: closeRef.current, pinkBtn: pinkRef.current, }; }); if (!open) return null; return ( <div> <br /> <button ref={closeRef} onClick={onClose}> &times; </button> <h1>Color Change</h1> <div> <div ref={pinkRef}>color1</div> </div> </div> ); } export default React.forwardRef(CustomModal);
CustomModal.js
 
위 코드는 useImperativeHandle Hook을 포함한 CustomModal 컴포넌트의 전체 코드입니다. ref를 전달받는 자식 컴포넌트인 CustomModal에서 React.forwardRef로 감싼 후 export 해야 useImperativeHandle Hook의 인자로 ref를 전달받을 수 있기 때문에 마지막 코드에 export default React.forwardRef(CustomModal)를 넣어줍니다.
 
<button onClick={() => { modalRef.current.pinkBtn.style = "width:50px; height:50px; background:pink;"; }} > Pink Btn </button>;
App.js
 
마지막으로 App.jsx로 돌아와 Pink Btn 버튼 onClick 이벤트 핸들러에modalRef.current.pinkBtn.style을 넣어 css 스타일을 변경해줍니다. width:50px; height:50px; background:pink;의 값을 설정해 너비, 높이와 배경색을 변경해주었습니다. 아래 그림 9-n은 Pink Btn을 클릭하여 color1의 스타일을 바꾼 결과입니다.
 
그림 9-3그림 9-3
그림 9-3
 
위와 동일한 방식으로 Skyblue Btn과 Tomato Btn을 만들어 원래 만들고자 했던 앞서 그림 9-1과 같은 어플리케이션을 완성합니다. 아래는 최종 코드입니다.
 
function App() { const [open, setOpen] = useState(false); const modalRef = useRef(); return ( <> <button onClick={() => setOpen(true)}>Open</button> <button onClick={() => { modalRef.current.pinkBtn.style = "width:50px; height:50px; background:pink;"; }} > Pink Btn </button> <button onClick={() => { modalRef.current.skyblueRefBtn.style = "width:50px; height:50px; background:skyblue;"; }} > Skyblue Btn </button> <button onClick={() => { modalRef.current.tomatoBtn.style = "width:50px; height:50px; background:tomato;"; }} > Tomato Btn </button> <CustomModal ref={modalRef} open={open} onClose={() => setOpen(false)} /> </> ); }
App.js
 
function CustomModal({ open, onClose }, ref) { const closeRef = useRef(); const pinkRef = useRef(); const skyblueRef = useRef(); const tomatoRef = useRef(); useImperativeHandle(ref, () => { return { closeBtn: closeRef.current, pinkBtn: pinkRef.current, skyblueRefBtn: skyblueRef.current, tomatoBtn: tomatoRef.current, }; }); if (!open) return null; return ( <div> <br /> <button ref={closeRef} onClick={onClose}> &times; </button> <h1>Color Change</h1> <div> <div ref={pinkRef}>color1</div> <div ref={skyblueRef}>color2</div> <div ref={tomatoRef}>color3</div> </div> </div> ); } export default React.forwardRef(CustomModal);
CustomModal.js