프로젝트를 진행하다가 부모 컴포넌트에서 자식컴포넌트의 함수를 써야했다. useState는 익숙하게 사용했지만 해당함수를 사용하기 위해서 좋은 방법은 아닌것 같았다. 하여 방법을 찾다 기록해두기로 한다.
forwardRef는 부모 컴포넌트로부터 ref 속성을 받는 한 컴포넌트를 만든다. 그리고 그 속성을 받은 컴포넌트로부터 또 자식에게 그 속성을 또 전달하게 한다. 아래 그림을 보면 조금 더 이해하기 쉽다.
useRef를 사용하면 컴포넌트의 instance value가 생성된다. 그리고 그 instance value는 DOM 요소를 조작할수 있게 한다.
// 부모 컴포넌트
const sampleRef = useRef({});
return (
<ChildComponent ref={sampleRef} ...
)
// 자식 컴포넌트
const ChildComponent = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
// 부모에서 사용하고 싶었던 함수
parentsLikesThisFunc,
}));
...
});
부모 컴포넌트에서 props를 넘겨주는 대신 자식 컴포넌트의 DOM에 접근할 수 있는 ref 를 얻는다. 그리고 자식 컴포넌트를 forwardRef로 감싼다. 그러면 인자로 props와 ref를 받을 수 있다. useImperativeHandle를 이용하여 부모에게 노출될 인스턴스의 값을 사용자 정의할 수 있다. 첫 번째 인자에는 ref, 두 번째 인자에는 ref를 활용하여 접근할 함수를 넘겨준다.
// 부모 컴포넌트
function Body() {
const handleKeyRef = useRef<any>();
return (
<BodySection
tabIndex={0}
onKeyDown={(e) => handleKeyRef.current.handleKeyDown(e)}>
<KeyPad KeyRef={handleKeyRef}/>
</BodySection>
);
}
// 자식 컴포넌트
const KeyPad = forwardRef(
({ darkMode, value, setValue, KeyRef }: PropsInfo) => {
// body 컴포넌트에서 사용할 함수
useImperativeHandle(KeyRef, () => ({
handleKeyDown,
}));
})
div요소에 대한 onkeyDown이벤트 처리를하면서 오류가 생겨 해결법을 찾았다.
React에서 div 요소의 onkeyDown이벤트를 처리하려면 요소의 탭 인덱스를 0으로 설정한다. tabIndex={0}.
Div 요소는 기본적으로 초점을 맞출 수 없으므로 onKeyDown div에서 이벤트 를 처리하려면 요소에 tabIndex를 설정해야 한다.
이 tabIndex속성은 해당 요소가 포커스를 받을 수 있고 순차 키보드 탐색( 키 사용)에 참여하는 위치를 나타낸다. Tab요소가 tabIndex = 0으로 설정되면 요소는 양수 tabIndex값 이후에 순차적 키보드 탐색에서 초점을 맞출 수 있다.
tabIndex속성은 해당 요소가 포커스를 받을 수 있고 순차 키보드 탐색( 키 사용)에 참여하는 위치를 나타냅니다.
Ref 전달하기
휴먼스케이프 기술 블로그
React 부모 컴포넌트에서 자식 컴포넌트 함수 호출하기 - useImperativeHandle
React의 Div 요소에 대한 onKeyDown 이벤트 처리