LoginSignup
2
3

More than 1 year has passed since last update.

【React】(親から子|子から親)の関数を呼び出す

Last updated at Posted at 2021-05-10

親から子の関数を呼び出す

実装方法としては、子供側の参照を親から触れるようにしてやり、
参照を通じて子供側の関数を呼び出せれるようにしてやります。

子供側の実装

const ChildrenBase: React.ForwardRefRenderFunction<
  { printId: () => void },
  {
    id: string;
  }
> = ({ id }, ref) => {
  // 親から呼ばれる関数を定義
  useImperativeHandle(ref, () => ({
    printId() {
      console.log(id);
    },
  }));

  return <div>Children</div>;
};
const Children = forwardRef(ChildrenBase);

forwardRefuseImperativeHandleを使って実現します。
forwardRefでChildrenを参照し、useImperativeHandleで関数を参照に付与します。

親側の実装

const Parent: React.FC = () => {
  const childRef = useRef<{ printId: () => void }>();
  useEffect(() => {
    childRef.current?.printId();
  }, [childRef.current]);
  return <Children id={'1234567'} ref={childRef} />;
};

export default Parent;

親側は参照を通して、子供側の関数を呼び出します。

子から親の関数を呼び出す

今度は逆のパターンで、子供側から親側の関数を呼び出すパターンです。
実装方法として、今回はpropsで渡す実装ではなく、全ての子供に親の関数を呼べるようにしてやります。
ユースケースとしては Layout 等の共通のコンポーネントで、子供が使おうと思ったら Layout の関数が使える
ようなケースになるかと思います。

子供側の実装

type ChildrenDispatchProps = {
  printId?: (id: string) => void;
};

const Children: React.FC<ChildrenDispatchProps & { id: string }> = ({
  printId,
  id,
}) => {
  return <button onClick={() => printId(id)}>ボタン</button>;
};

親から渡される関数は ? 付きで定義しないとTypeエラーになります。

親側の実装

const Parent: React.FC = ({ children }) => {
  const printId = (id: string) => {
    console.log(id);
  };
  const childWithProps = React.Children.map(children, (child) => {
    if (React.isValidElement(child)) {
      const dispatch: ChildrenDispatchProps = {
        printId: printId,
      };
      return React.cloneElement(child, { ...dispatch });
    }
    return child;
  });
  return <div>{childWithProps}</div>;
};

const App: React.FC = () => {
  return (
    <Parent>
      <Children id={'1'} />
      <Children id={'2'} />
    </Parent>
  );
};

cloneElement で子供に親側で定義した関数を付与してやります。
↑のようにする事で、子供側は ChildrenDispatchProps を受け取るようにした場合、その子供は
親の関数 printId を使えるようになります。

React.cloneElementReact.isValidElement 等は以下リンク先を参照
React の最上位 API - React

参考リンク

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3