React:useRefの動作確認

環境

React:v18.3.1

Tips

  • コンポーネントが生成されてから破棄されるまで維持される、変更可能なオブジェクト。
  • useImperativeHandle関数を利用すると、親から子のメソッドを実行することができる。

子コンポーネントの特定タグへの参照を利用する

App.tsxの内容(重要でない)

import { ReactNode, useEffect, useLayoutEffect } from 'react';
import Parent from './Parent.tsx';

function App(): ReactNode {
  useLayoutEffect(() => {
    console.log('App useLayoutEffect');
  });

  useEffect(() => {
    console.log('App useEffect');
  });

  return (
    <>
      あいうえお
      <Parent />
    </>
  );
}

export default App;

Parent.tsxの内容

import {
  MutableRefObject, ReactNode, useEffect, useLayoutEffect, useRef, useState,
} from 'react';
import Child1 from './Child1.tsx';

function Parent(): ReactNode {
  const [child1Value, setChild1Value] = useState<string>('Child1の初期値');
  const [parentValue1, setParentValue1] = useState<string>('Parentの初期値');

  const refStrChildBtn: MutableRefObject<HTMLButtonElement> = useRef(null);

  function parentBtnClickFunc() {
    alert('parentBtnClickFunc');
    setChild1Value('親からStateが変更されました');
  }

  useLayoutEffect(() => {
    console.log('Parent useLayoutEffect');
    refStrChildBtn.current.innerHTML = 'aiueo';
  });

  useEffect(() => {
    console.log('Parent useEffect');
  });

  return (
    <>
      <div>
        親:
        {parentValue1}
      </div>
      <button type="button" onClick={parentBtnClickFunc}>
        親ボタン
      </button>
      <Child1
        childProp={child1Value}
        parentStateFunc={setParentValue1}
        ref={refStrChildBtn}
      />
    </>
  );
}

export default Parent;

Child1.tsxの内容

import React, {
  forwardRef, LegacyRef, useEffect, useLayoutEffect,
} from 'react';

type Child1Props = {
  childProp: string,
  parentStateFunc: Function
};

// function Child1({ childProp, parentStateFunc }: Child1Props): ReactNode {
const Child1: React.ForwardRefExoticComponent<any> = forwardRef(
  ({ childProp, parentStateFunc }: Child1Props, ref: LegacyRef<HTMLButtonElement>) => {
    function childBtnClickFunc(): void {
      alert('childBtnClickFunc');
      parentStateFunc('子からStateが変更されました');
    }

    useLayoutEffect(() => {
      console.log('Child1 useLayoutEffect');
    });

    useEffect(() => {
      console.log('Child1 useEffect start Promise date = ', Date());
    });

    return (
      <>
        <div>
          子:
          {childProp}
        </div>
        <div>
          <button
            type="button"
            onClick={childBtnClickFunc}
            ref={ref}
          />
        </div>
      </>
    );
  },
);
// }

export default Child1;

結果

Parent.tsx の useLayoutEffect でボタンの参照を経由して
innerHTMLを編集していることの動作確認をすれば良い。

(初期表示後に子のボタンの文字列が「aiueo」となっていることを確認すれば良い。)

コメント

タイトルとURLをコピーしました