forwardRef는 component간 ref를 전달하기 위해 사용하는 Function 입니다.
React에서는 ref를 props로 직접전달하지 않고 fowardRef를 통하여 해당 ref를 전달합니다.
그러면, 일반적으로 사용될 수 있는 공통 팝업을 통해 구현해보겠습니다.
팝업은,
- Transition 효과가 적용되어야 하며
- close 함수를 제공하여햐 합니다.
1. forwardRef를 사용하여 component 생성
- 인자로 props, ref 전달받는 component를 생성합니다.
- ref는 해당 팝업의 close함수를 "상위 컴포넌트에서 사용하고자 참조하기 위해서" 사용합니다.
// 제공하기 원하는 함수 정의
interface ISlidePopupRef {
close(): void;
}
// props type 정의
type Props = {
title: string; // 팝업 제목
// Event 정의
onExit?(): void;
onExited?(): void;
onEntered?(): void;
onClickBack?(): void;
children: JSX.Element; // 팝업 content
};
const Slidepopup = React.forwardRef<ISlidePopupRef, Props>(
({ title, onExit, onEntered, onExited, onClickBack, children }, ref)
2. useImperativeHanle hook : 상위 컴포넌트에서 제공하고자 하는 함수 정의
const [isPopupShow, setPopupShow] = useState(true);
const close = () => {
setPopupShow(false);
onClickBack?.();
};
useImperativeHandle(ref, () => ({ close }));
3. propTypes 정의 : 전달하는 prop의 type을 정의합니다.
- 필수가 아니기 때문에 오류가 발생하지는 않지만, isRequired나 type 오류 방지를 위해 작성합니다.
SlidePopup.propTypes = {
title: PropTypes.string.isRequired,
onExit: PropTypes.func,
onExited: PropTypes.func,
onEntered: PropTypes.func,
onClickBack: PropTypes.func,
children: PropTypes.element.isRequired,
ref: PropTypes.func,
};
4. 상위 컴포넌트에서 사용
- useRef를 통해 참조값 설정
- 전달받은 ref의 close function 호출
const popupRef = React.useRef<{ close: () => void }>(null);
....
<SlidePopup ref={popupRef} title="팝업 Todo">
<ListStyled>
<li>할일1</li>
<li>할일2</li>
<button onClick={()=>popupRef.current.close()}>닫기</button>
</ListStyled>
</SlidePopup>
이처럼 forwardRef를 사용하면 ref를 전달하여 컴포넌트안의 element를 참조하거나
해당 컴포넌트의 특정 함수를 호출할 수 있습니다.
※ 최종 팝업 코드
import React, { useImperativeHandle, useRef, useState } from 'react';
import { CSSTransition } from 'react-transition-group';
import PropTypes from 'prop-types';
export interface ISlidePopupRef {
close(): void;
}
type Props = {
title: string;
onExit?(): void;
onExited?(): void;
onEntered?(): void;
onClickBack?(): void;
pageBottom?: JSX.Element;
children: JSX.Element;
};
const SlidePopup = React.forwardRef<ISlidePopupRef, Props>(
({ title, onExit, onEntered, onExited, onClickBack, pageBottom, children }, ref) => {
const nodeRef = useRef(null);
const [isPopupShow, setPopupShow] = useState(true);
const close = () => {
setPopupShow(false);
onClickBack?.();
};
useImperativeHandle(ref, () => ({ close }));
return (
<CSSTransition
appear
nodeRef={nodeRef}
in={isPopupShow}
unmountOnExit
classNames={'popup-right'}
timeout={300}
onEntered={onEntered}
onExit={onExit}
onExited={onExited}
>
<PageContainer ref={nodeRef}>
<>
<TitleContainer>
<BackBtn onClick={close} />
<Title>{title}</Title>
</TitleContainer>
<PageContent>{children}</PageContent>
</>
</PageContainer>
</CSSTransition>
);
}
);
SlidePopup.displayName = 'SlidePopup';
SlidePopup.propTypes = {
title: PropTypes.string.isRequired,
onExit: PropTypes.func,
onExited: PropTypes.func,
onEntered: PropTypes.func,
onClickBack: PropTypes.func,
children: PropTypes.element.isRequired,
ref: PropTypes.func,
};
export default SlidePopup;
[React] Back 버튼으로 Modal 제어하기(2) (0) | 2023.02.09 |
---|---|
[React] Back 버튼으로 Modal 제어하기(1) (0) | 2023.02.07 |
React Transition Modal 적용 (0) | 2023.01.27 |
React Popup(팝업) 생성하기 (0) | 2023.01.25 |
React alias 설정시 Code Hint 설정 (0) | 2023.01.20 |
댓글 영역