function FancyButton(props) {
return (
<button className="FancyButton">
{props.children}
</button>
);
}
// 재사용할 컴포넌트 prop에 ref 사용
// ref는 button DOM을 직접 가리킴
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// 재사용하는 버튼에 ref를 생성하고 컴포넌트에 전달
const ref = React.useRef(null);
<FancyButton ref={ref}>Click me!</FancyButton>;
function logProps(WrappedComponent) {
const LogProps = (props) => {
const prevProps = useRef();
useEffect(() => {
prevProps.current && console.log('old props:', prevProps.current);
console.log('new props:', props);
prevProps.current = props;
}, [props]);
return <WrappedComponent {...props} />;
}
return LogProps;
}
function FancyButton() {
//...
}
export default logProps(FancyButton);
다음과 같이 렌더링 되는 모든 prop을 기록하는 컴포넌트 함수가 있다 해보자.
버튼에 전달되는 모든 컴포넌트는 기록되지만, 이 경우 ref는 prop이 아니기 떄문에 전달되지 않는다.
ref를 가져오기 위해 FancyButton에 ref를 추가한다고 해도 가장 바깥쪽 컴포넌트인 logProps를 참고하게 된다.
import FancyButton from './FancyButton';
// FancyButton컴포넌트가 아닌 LogProps를 가리킴
// 만약 ref.current.focus()를 한다 가정해도 이는 전달되지 않음
const ref = useRef(null);
<FancyButton
label="Click Me"
handleClick={handleClick}
ref={ref}
/>;
// 내부 컴포넌트에 forwardedRef를 속성을 전달해 직접적으로 컴포넌트 DOM 획득
const LogProps = (props) => {
const prevProps = useRef();
useEffect(() => {
prevProps.current && console.log('old props:', prevProps.current);
console.log('new props:', props);
prevProps.current = props;
}, [props]);
const {forwardedRef, ...rest} = props;
return <Component ref={forwardedRef} {...rest}/>;
}
// ref를 받아 forwardedRef와 같은 일반적인 속성으로 logProp에 전달
function logProps(WrappedComponent) {
// props, ref을 받아 내부 컴포넌트에 대한 ref 전달
return React.forwardRef((props, ref) => {
return <LogProps {...props} forwardedRef={ref} />;
});
}