Estou armazenando um ref em minha loja redux e usando mapStateToProps para expor o ref para componentes que precisam de acesso a ele.
A referência armazenada é semelhante a:
ref={node => this.myRefToBePutInReduxGlobalStore = node}
Qual é o propType correto para este ref?
ref
prop é uma função com o primeiro argumento uma referência ao elemento DOM ou nulo. É uma função .propType
pararefs
, mas pode usá-lo paraprops
. Já que você o está passando para a redux store, ele é representado como umprop
likethis.props.myRefToBePutInReduxGlobalStore
.myRefToBePutInReduxGlobalStore
deve ser o tipo de nó, entãoPropTypes.node
deve funcionar para vocêPropType.object
porque ref é basicamente uma instância de classe que é um objeto. Portanto, quando você passa o elemento ref como um adereço, ele seria do tipo de objetoRespostas:
TL; DR
Se você deseja prop tipo um ref que espera apenas elementos DOM nativos, como um
div
ou uminput
, a definição correta é a seguinte: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) }) ])
Resposta ao problema específico descrito na postagem original
No exemplo da pergunta do OP, não é o tipo ref prop que precisa ser declarado, mas o material apontado pelo ref, e que será passado do redux usando
mapStateToProps
. O tipo de prop para um elemento DOM seria:myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element)
(se for um elemento DOM). Embora, eu:myElementToBePutInReduxGlobalStore
(um elemento não é uma referência)Resposta longa para a pergunta real
P: Qual é o proptype correto para um ref no React?
Exemplo de caso de uso:
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} /> }
Hoje, existem dois tipos de árbitros em reação:
{ current: [something] }
geralmente criado porReact.createRef()
auxiliar ouReact.useRef()
gancho[something]
como argumento (como a do exemplo OP)Observação: historicamente, você também pode usar uma string ref, mas ela é considerada legada e será removida do react
O segundo item é bastante simples e requer o seguinte tipo de prop:
PropTypes.func
.A primeira opção é menos óbvia porque você pode querer especificar o tipo de elemento apontado pelo ref.
Muitas boas respostas
ref
pode apontar para algo diferente do elemento DOM.Se você quiser ser totalmente flexível:
refProp: PropTypes.oneOfType([ PropTypes.func, PropTypes.shape({ current: PropTypes.any }) ])
O acima apenas reforça a forma do objeto ref w /
current
property. Funcionará sempre para qualquer tipo de ref. Para o propósito de usar o tipo de objeto, que é uma maneira de detectar quaisquer inconsistências durante o desenvolvimento , isso provavelmente é o suficiente. Parece muito improvável que um objeto com forma{ current: [any] }
e seja passado para umrefToForward
suporte, não seja um verdadeiro ref.No entanto , você pode querer declarar que seu componente não espera nenhum tipo de ref, mas apenas um certo tipo, dado o que ele precisa para esse ref.
Eu configurei um sandbox mostrando algumas maneiras diferentes de declarar um ref, mesmo algumas não convencionais, e então testando-as com muitos tipos de adereços. Você pode encontrá-lo aqui .
Se você espera apenas um ref apontando para um elemento de entrada nativo, não para qualquer HTML
Element
:refProp: PropTypes.oneOfType([ PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(HTMLInputElement) }) ])
Se você espera apenas um ref apontando para um componente da classe React:
refProp: PropTypes.oneOfType([ PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Component) }) ])
Se você espera apenas um ref apontando para um componente funcional usando
useImperativeHandle
para expor algum método público:refProp: PropTypes.oneOfType([ PropTypes.func, PropTypes.shape({ current: PropTypes.object }) ])
Observação: o tipo de prop acima é interessante porque também cobre componentes de reação e elementos DOM nativos, porque todos eles herdam o javascript base
Object
Não existe uma maneira única de declarar o tipo de suporte para um ref, depende do uso. Se o seu árbitro apontar para algo muito identificado, pode valer a pena adicionar um tipo específico de suporte. Caso contrário, apenas verificar a forma geral parece suficiente.
Nota sobre a renderização do lado do servidor
Se o seu código tiver que ser executado no servidor, a menos que você já tenha um ambiente DOM do polyfill,
Element
ou qualquer outro tipo do lado do cliente estaráundefined
em NodeJS. Você pode usar o seguinte calço para apoiá-lo:Element = typeof Element === 'undefined' ? function(){} : Element
As seguintes páginas do React Docs fornecem mais informações sobre como usar refs, objetos e callbacks , e também como usar o
useRef
ganchoResposta atualizada agradecendo a @Rahul Sagore, @Ferenk Kamra, @svnm e @Kamuela Franco
fonte
Element
não está definido na renderização do lado do servidor. Alguma solução para isso?Element = typeof Element === 'undefined' ? function(){} : Element
(sugerido por Ryan Florence em alguma edição do github). Se funcionar para você, posso adicioná-lo à minha resposta.if (!isBrowser) { global.Element = null; }
. Funcionou para mim.isBrowser = typeof window !== 'undefined';
Muito semelhante à postagem de @Pandaiolo,
PropTypes.elementType
agora foi adicionadoforwardedRef: PropTypes.oneOfType([ PropTypes.func, PropTypes.shape({ current: PropTypes.elementType }) ]),
Se estiver usando PropTypes> = 15.7.0
PropTypes.elementType
foi adicionado em 10 de fevereiro de 2019 neste PRfonte
elementType
não funcionou para mim, então, na verdade, testei vários tipos de adereços em diferentes tipos de componentes que podem ser apontados por um ref, em uma sandbox. Aqui estão os resultados: codesandbox.io/s/loving-benz-w6fbh . Não tenho certeza se cobri todas as possibilidades, mas parece que o proptype correto para o elemento DOM éinstanceOf(Element)
(ouobject
), para uma classe éinstanceOf(Component)
(ouobject
) e para o caso de uso específico de um componente funcional usandouseImperativeHandle
éobject
. Pensamentos?Eu apenas verifico a forma preferida e como PropType.object não é muito valioso, acabei usando este:
PropTypes.shape({ current: PropTypes.instanceOf(Element) })
fonte
Eu verifiquei todas as respostas acima, mas recebo um aviso da reação, então pesquisei muito e achei a resposta certa.
import React, { Component } from 'react'; ComponentName.propTypes = { reference: PropTypes.oneOfType([ PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Component) }), ]), };
fonte