親コンポーネントのオブジェクトの状態によって子コンポーネントを動的に切り替える。かつ、親コンポーネントのマウスイベントから子コンポーネントのメソッドを呼び出す。
useRecoil を使うのがミソか。
import { useEffect, useState, forwardRef, useRef, useImperativeHandle, Children, } from "react"; import { useRecoilState } from "recoil"; import { flagState, positionState } from "./state.jsx"; const Klass1 = forwardRef((props, ref) => { const [position, setPosition] = useRecoilState(positionState); useImperativeHandle(ref, () => ({ updatePosition, })); const updatePosition = (event) => { setPosition({ x: event.clientX, y: event.clientY, }); }; return <>{props.children}</>; }); const Klass2 = forwardRef((props, ref) => { const [position, setPosition] = useRecoilState(positionState); useImperativeHandle(ref, () => ({ updatePosition, })); const updatePosition = (event) => { setPosition((prev) => { return { x: prev.x + 1, y: prev.y + 1, }; }); }; return <>{props.children}</>; }); const Factory = ({ flag, children, childRef }) => { if (flag) { return <Klass1 ref={childRef}>{children}</Klass1>; } else { return <Klass2 ref={childRef}>{children}</Klass2>; } }; const MyComponents = () => { const [flag, setFlag] = useRecoilState(flagState); const [position, setPostion] = useRecoilState(positionState); const childRef = useRef(); const style = { width: 120, height: 120, backgroundColor: "green", }; return ( <Factory flag={flag} childRef={childRef}> <div id="my_components" style={style} onMouseMove={(event) => childRef.current.updatePosition(event)} > <label> x={position.x}, y={position.y} </label> </div> </Factory> ); }; export default MyComponents;