1. ホーム
  2. reactjs

[解決済み] Reactのrefの正しいproptypeは何ですか?

2022-11-03 16:32:29

質問

私はreduxストアにrefを保存し、それにアクセスする必要があるコンポーネントのためにrefを公開するためにmapStateToPropsを使用しています。

格納されているrefは以下のような感じです。

ref={node => this.myRefToBePutInReduxGlobalStore = node}

このrefの正しいpropTypeは何でしょうか?

どのように解決するのですか?

TL;DR

のようなネイティブな DOM 要素のみを期待する Ref を prop タイプしたい場合、例えば div または input であるならば、正しい定義は以下の通りです。

refProp: PropTypes.oneOfType([
    // Either a function
    PropTypes.func, 
    // Or the instance of a DOM native element (see the note about SSR)
    PropTypes.shape({ current: PropTypes.instanceOf(Element) })
])

元の投稿で説明された特定の問題に対する回答

質問の例では、宣言する必要があるのはrefのprop型ではなく、refが指すものであり、それはreduxから mapStateToProps . DOM要素のプロップタイプは、次のようになります。 myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element) (となります(DOM要素であれば)。とはいえ、私なら

  1. にリネームします。 myElementToBePutInReduxGlobalStore (要素は参照ではありません)
  2. reduxストア内にシリアライズ不可能なデータを保存しないようにする。
  3. propsで要素を渡さないようにする ReactのエンジニアであるSeb Markbage氏が説明するように

実際の質問に対する長い回答

Q: Reactにおけるrefの正しいproptypeは何ですか?

使用例です。

function FancyInput({ inputRef }) {
    return (
        <div className="fancy">
            Fancy input
            <input ref={inputRef} />
        </div>
    )
}

FancyInput.propTypes = {
    inputRef: ???   // What is the correct prop type here?
}

function App(props) {
    const inputRef = React.useRef()
    useLayoutEffect(function focusWhenStuffChange() {
        inputRef.current?.focus()
    }, [props.stuff])
    return <FancyInput inputRef={inputRef} />
}


現在、reactには2種類のrefが存在します。

  1. 以下のようなオブジェクトです。 { current: [something] } 通常 React.createRef() ヘルパーか React.useRef() フック
  2. コールバック関数で [something] を引数として受け取るコールバック関数 (OP例のようなもの)。

注:歴史的には、文字列参照を使うこともできましたが ではレガシーとされている と見なされ、reactから削除される予定です。

2つ目の項目は非常にシンプルで、以下のようなprop型を必要とします。 PropTypes.func .

最初の選択肢は、refが指す要素のタイプを指定したいかもしれないので、あまり明白ではありません。

多くの良い答え

ref は、DOM要素以外のものを指すことができます。

完全にフレキシブルにしたい場合。

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.any })
])

上記は、object ref w/の形状を強制しているだけです。 current プロパティの形状を強制しているだけです。これはどのような種類のrefに対しても常に機能します。prop 型を使用する目的、つまり矛盾を発見する方法として を開発するときに を発見する方法であるprop型を使用する目的では、おそらくこれで十分です。と思われます。 非常に低い の形状を持つオブジェクトが { current: [any] } に渡され、さらに refToForward プロップに渡されると ではなく は実際の参照である。

しかし を期待しないことを宣言したいかもしれません。 任意の を期待せず、ある特定のタイプだけを期待すると宣言したいかもしれません。

私は、ref を宣言するいくつかの異なる方法を紹介するサンドボックスをセットアップし、従来とは異なるものも含め、多くのプロップ タイプでそれらをテストしています。 ここで見つけることができます。 .


ネイティブの入力要素を指す参照だけを期待する場合は 任意の HTML Element :

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.instanceOf(HTMLInputElement) })
])

Reactクラスのコンポーネントを指すrefだけを期待する場合。

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.instanceOf(Component) })
])

を使用して機能コンポーネントを指す参照だけを期待する場合。 useImperativeHandle を使って、ある公開メソッドを公開することだけを期待する場合。

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.object })
])

注:上記のプロップタイプは、リアクトコンポーネントやネイティブDOM要素も対象としているため、興味深いもので、これらはすべてベースのjavascriptを継承しているからです。 Object


Refのプロップタイプを宣言する良い方法は一つもなく、用途に依存します。もし、あなたの参照が非常に特定されたものを指しているならば、特定のプロップタイプを追加する価値があるかもしれません。そうでなければ、一般的な形状をチェックするだけで十分なようです。


サーバーサイドレンダリングに関する注意事項

サーバー上でコードを実行する必要がある場合、すでにDOM環境をポリフィルしている場合を除きます。 Element またはその他のクライアント側の型は undefined になります。以下のシムで対応可能です。

Element = typeof Element === 'undefined' ? function(){} : Element


以下のReact Docsのページがより深い洞察を与えてくれます。 を使用する方法について、オブジェクトとコールバックの両方が記載されています。 そしてまた の使い方 useRef フック

回答更新:@Rahul Sagore、@Ferenk Kamra、@svnm、および @Kamuela Franco に感謝します。