Reactのrefの正しいproptypeは何ですか?


87

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

保存される参照は次のようになります。

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

この参照の正しいpropTypeは何ですか?


8
refはシリアル化できないため、Reduxストアに配置することはお勧めできません。それでも、refpropに渡される値は、最初の引数がDOM要素またはnullへの参照を持つ関数です。それは関数です。
rishat 2017

5
あなたは使用することはできませんpropType ためrefs、しかし、あなたはそれを使用することができますprops。あなたはそれをreduxストアに渡しているので、それはproplikeとして表されthis.props.myRefToBePutInReduxGlobalStoreます。myRefToBePutInReduxGlobalStoreノードのタイプである必要があるのでPropTypes.node、あなたのために働くはずです
理由

PropType.objectrefは基本的にオブジェクトであるクラスインスタンスだからだと思います。したがって、ref要素を小道具として渡すと、オブジェクトタイプになります
HridayModi18年

回答:


99

TL; DR

adivや、などのネイティブDOM要素のみを期待するrefをprop型で入力する場合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) })
])

元の投稿に記載されている特定の問題への回答

OP質問の例では、宣言する必要があるのはref propタイプではなく、refが指すものであり、mapStateToProps。を使用してreduxから渡されます。DOM要素のプロップタイプは次のようになります:(myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element)それがDOM要素の場合)。しかし、私はそうします:

  1. 名前を変更しますmyElementToBePutInReduxGlobalStore(要素は参照ではありません)
  2. シリアル化できないデータをreduxストア内に保存しないでください
  3. ReactエンジニアのSebMarkbageが説明しているように、小道具に要素を渡すことは避けてください

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

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種類の参照が存在します。

  1. 次のようなオブジェクト:{ current: [something] }、通常はReact.createRef()ヘルパーまたはReact.useRef()フックによって作成されます
  2. [something]引数として受け取るコールバック関数(OPの例のように)

注:歴史的には、文字列refを使用することもできますが、これはレガシーと見なされ、reactから削除されます

2番目の項目は非常に単純で、次の小道具タイプが必要ですPropTypes.func

refが指す要素のタイプを指定したい場合があるため、最初のオプションはあまり明白ではありません。

多くの良い答え

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

完全に柔軟になりたい場合:

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

上記は、currentプロパティ付きのオブジェクト参照の形状を強制するだけです。あらゆる種類の参照に対して常に機能します。開発時に不整合を見つける方法である小道具タイプを使用するためには、おそらくこれで十分です。形状があり、小道具に渡されるオブジェクトが実際の参照ではない可能性非常に低いようです。{ current: [any] }refToForward

ただし、コンポーネントがどのような種類の参照期待せず、特定のタイプのみを期待していることを宣言することをお勧めします。

参照を宣言するためのいくつかの異なる方法を紹介するサンドボックスをセットアップしました。これは、従来とは異なるものもあり、多くの小道具タイプでテストします。あなたはここでそれを見つけることができます


HTMLではなくネイティブ入力要素を指すrefのみが必要な場合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パブリックメソッドを公開するために使用する機能コンポーネントを指すrefのみが必要な場合:

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

注:上記のpropタイプは、reactコンポーネントとネイティブDOM要素もカバーしているため、興味深いものです。これらはすべてベースJavaScriptを継承しているためです。 Object


refのpropタイプを宣言する良い方法はありません。それは、使用法によって異なります。参照が非常に識別されたものを指している場合は、特定の小道具タイプを追加する価値があります。それ以外の場合は、一般的な形状を確認するだけで十分なようです。


サーバー側のレンダリングに関する注意

すでにDOM環境をポリフィルしていない限り、コードをサーバー上で実行する必要がある場合、Elementまたは他のクライアント側のタイプがundefinedNodeJSにある場合。次のシムを使用してサポートできます。

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

次のReactDocsページでは、オブジェクトとコールバックの両方のrefの使用方法、およびフックの使用方法について詳しく説明しています。useRef

@ Rahul Sagore、@ Ferenk Kamra、@ svnm、および@KamuelaFrancoへの回答の更新された感謝


2
それは与えElement、サーバ側のレンダリングに定義されていません。それに対する解決策はありますか?
RahulSagore19年

いい視点ね。このシムはどうですか:(Element = typeof Element === 'undefined' ? function(){} : Elementいくつかのgithubの問題でRyanFlorenceによって提案されました)。それがあなたのために働くならば、私はそれを私の答えに加えることができます。
パンダイオロ

私はそれを理解し、これを追加しましたif (!isBrowser) { global.Element = null; }。私のために働いた。isBrowser = typeof window !== 'undefined';
RahulSagore19年

素晴らしい答え。TL; DRが応答のトップになることを望んでいます。
KamuelaFranco20年

12

@Pandaioloの投稿と非常によく似ていますが、

PropTypes.elementType 追加されました

forwardedRef: PropTypes.oneOfType([
  PropTypes.func,
  PropTypes.shape({ current: PropTypes.elementType })
]),

PropTypes> = 15.7.0を使用している場合PropTypes.elementTypeこのPRで2019年2月10日に追加されました


@svnmに感謝します。これを反映するように回答を更新しました。これにより、回答が簡単になります。
パンダイオロ

1
結局、それelementTypeは私にとってはうまくいきませんでした、それで私は実際にサンドボックスで、refによって指し示されることができる異なる種類のコンポーネントでたくさんの小道具タイプをテストしました。結果は次のとおりです:codesandbox.io/s/loving-benz-w6fbh。すべての可能性を網羅したかどうかはわかりませんが、DOM要素の正しいproptypeはinstanceOf(Element)(またはobject)、クラスの場合はinstanceOf(Component)(またはobject)、useImperativeHandleそれを使用する機能コンポーネントの特定のユースケースの場合はobjectです。考え?
パンダイオロ

9

私は好ましい方法をチェックするだけで、PropType.objectはあまり価値がないので、これを使用することになりました。

PropTypes.shape({ current: PropTypes.instanceOf(Element) })

1

上記のすべての回答を確認しましたが、反応から警告が表示されたので、よく調べて正しい答えを得ました。

import React, { Component } from 'react';

ComponentName.propTypes = {
  reference: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.shape({ current: PropTypes.instanceOf(Component) }),
  ]),
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.