[리액트] 부모 컴포넌트에서 자식 컴포넌트 함수 사용하기

달하·2022년 1월 25일
0

useRef

const refContainer = useRef(initialValue);

useRef는 .current 프로퍼티로 전달된 인자로 초기화된 변경 가능한 ref 객체를 반환합니다.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

본질적으로 useRef는 .current 프로퍼티에 변경 가능한 값을 담고 있는 “상자”와 같습니다.
useRef는 매번 렌더링을 할 때 동일한 ref 객체를 제공하며, 내용이 변경될때 따로 알려주지 않습니다. .current 프로퍼티를 변형하더라도 리렌더링은 발생하지 않습니다.

참조

forwardRef

HTML엘리먼트가 아닌 JSX에 refprop을 전달했을 때 자식이 ref를 받기 위해서 forwardRef가 사용됩니다.
아래의 예에서 FancyButton은 React.forwardRef를 사용하여 전달된 ref를 얻고, 그것을 렌더링 되는 DOM button으로 전달합니다.

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// 이제 DOM 버튼으로 ref를 작접 받을 수 있습니다.
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

이런 방법으로 FancyButton을 사용하는 컴포넌트들은 button DOM 노드에 대한 참조를 가져올 수 있고, 필요한 경우 DOM button을 직접 사용하는 것처럼 접근할 수 있습니다.

위의 예시에서 어떤 일이 일어나는지 단계별 설명

1. React.createRef를 호출해서 React ref를 생성하고 ref 변수에 할당합니다.
2. ref를 JSX 속성으로 지정해서 <FancyButton ref={ref}>로 전달합니다.
3. React는 이 ref를 forwardRef 내부의 (props, ref) => ... 함수의 두 번째 인자로 전달합니다.
4. 이 ref를 JSX 속성으로 지정해서 <button ref={ref}>으로 전달합니다.
5. ref가 첨부되면 ref.current는 <button> DOM 노드를 가리키게 됩니다.

참조

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])

useImperativeHandle은 ref를 사용할 때 부모 컴포넌트에 노출되는 인스턴스 값을 사용자화(customizes)합니다.

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

위의 예시에서

<FancyInput ref={inputRef} />

를 렌더링한 부모 컴포넌트는 inputRef.current.focus()를 호출할 수 있습니다.

참조

활용 예

import { forwardRef, useImperativeHandle, useState } from "react";

export default function Score({isStart}, ref){

    const [score, setScore] = useState(0);

    useImperativeHandle(ref, ()=>({
        addScore: () => setScore(score => score = score + 100),
        start: () => setScore(0)
    }))

    return(
        <div>
            {isStart ? 
        <h1>{score}</h1> :
        <h1>점수 : {score}</h1>
        }
        </div>
    )
}
Score = forwardRef(Score);

맨 하단의 Score = forwardRef(Score);를 통해 Score컴포넌트가 부모로 부터 ref를 받을 수 있게 되었다.
Score 컴포넌트의 useImperativeHandle메소드와 같이 부모 컴포넌트로부터 받은 ref를 첫 번째 prop으로 전달한 후 두 번째 prop으로 부모 컴포넌트에서 사용하고자 하는 함수를 위와같은 형식으로 작성해주면 된다.
부모 컴포넌트에서는 scoreRef.current.addScore();와 같은 식으로 사용하면 된다.

profile
할 수 있다

0개의 댓글