useInjectedProps
2024. 3. 20. 14:58ㆍ코반주반
컴포넌트의 Props를 일부 오버라이드하면서 인터페이스를 바꾸고, 컴포넌트가 동일한 ref를 갖게(re-render 가능하게) 해주는 훅을 만들어보자.
Implementation
export default function useInjectedProps<
C extends React.FC<any>,
I extends Partial<Record<keyof ComponentProps<C>, any>>,
>(_Component: C, injectedProps: I) {
// 훅의 인자로 받은 컴포넌트를 저장합니다.
const Component = useRef<any>(_Component);
// 상태 변경이 일어나면서 컴포넌트 호출이 일어날 경우 injectedProps가 컴포넌트로 자연스럽게 주입 될 수 있게 합니다.
Component.current = (props: Omit<ComponentProps<C>, keyof I>) => {
return <_Component {...props} {...injectedProps} />;
};
// 컴포넌트의 ref를 고정시키기 위해 빈 배열의 useCallback 훅을 사용합니다.
return useCallback((props) => Component.current(props), []) as React.FC<
Omit<ComponentProps<C>, keyof I>
>;
}
Use Case
type ButtonProps = {
onClick: Function;
};
const Button = ({ onClick }: ButtonProps) => {
return <button onClick={onClick}>Hello World</button>;
};
type ButtonWithTextProps = ButtonProps & {
text: string;
};
const ButtonWithText = ({ onClick, text }: ButtonWithTextProps) => {
return <button onClick={onClick}>{text}</button>;
};
const Renderer = ({ RenderButton }: { RenderButton: React.FC<ButtonProps> }) => {
return <RenderButton onClick={() => alert('Hello World')} />;
};
const UseCase = () => {
const RenderButton = useInjectedProps(ButtonWithText, {
text: 'World Hello',
});
return <Renderer RenderButton={RenderButton} />;
};
//===> <button>World Hello</button>
reference
https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md