什么是正确的原型为一个参考反应?

我在 redux 存储中存储了一个 ref,并使用 mapStateToProps 公开需要访问它的组件的 ref。

存储的 ref 类似于:

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

这个参考的正确 protype 是什么?

75513 次浏览

DR

If you want to prop type a ref that only expects native DOM elements, such as a div or an input, the correct definition is the following:

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 支持类型,而是 ref 指向的内容,这些内容将使用 mapStateToProps从 redux 传递。DOM 元素的 Prop 类型应该是: myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element)(如果它是 DOM 元素)。不过,我会:

  1. 将其重命名为 myElementToBePutInReduxGlobalStore(元素不是 ref)
  2. Avoid storing non-serializable data inside redux store
  3. 避免传递道具 中的元素,正如 React 工程师 Seb Markbage 所解释的那样

实际问题的长答案

问: 《反应》中裁判的正确原型是什么?

示例用例:

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} />
}

Today, two kind of refs exist in react:

  1. 这样的对象: { current: [something] },通常由 React.createRef()助手或者 React.useRef()钩子
  2. 一个回调函数,它将接收 [something]作为其参数(类似于 OP 示例中的参数)

Note: historically, you could also use a string ref, but 它被认为是遗产 and will be removed from react

第二个项目非常简单,需要以下道具类型: PropTypes.func

The first option is less obvious because you might want to specify the type of element pointed by the ref.

很多好答案

ref可以指向 DOM 元素之外的其他内容。

如果你想完全灵活:

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

以上只是强制对象 ref w/current属性的形状。它将在任何时候工作的任何裁判类型。对于使用道具类型的目的,这是一种发现任何不一致的 when you develop的方法,这可能就足够了。看起来 不太可能一个具有 { current: [any] }形状的物体,被传递给 refToForward支柱,那么 没有就是一个实际的参考。

但是 ,您可能希望声明您的组件并不期望使用 任何类型的 ref,而只是某种特定类型的 ref,因为它需要这种 ref 的目的是什么。

我已经设置了一个沙箱,展示了一些不同的方式来声明一个引用,甚至一些非常规的,然后测试他们与许多道具类型。You can find it here.


如果您只期望一个指向本机输入元素的 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指向函数组件的 ref 公开一些公共方法:

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

注意: 上面的道具类型很有趣,因为它还包含了反应组件和本机 DOM 元素,因为它们都继承了基本的 javascript Object


没有一种好的方法可以声明 ref 的道具类型,它取决于用法。如果你的参考指向一些非常明确的东西,它可以是值得添加一个特定的道具类型。否则,仅仅检查大体形状似乎就足够了。


关于服务器端呈现的注意事项

如果您的代码必须在服务器上运行,除非您已经填充了 DOM 环境,否则在 NodeJS 中,Element或任何其他客户端类型都将是 undefined。你可以用以下垫片来支撑:

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

下面的 React Docs 页面提供了更多关于 关于如何使用引用,包括对象和回调如何使用 useRef钩子的信息

回复更新感谢@Rahul Sagore,@Ferenk Kamra,@svnm,和@Kamuela Franco

我只检查首选的方式,因为 对象不是很有价值,我最终使用这个:

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

与@Pandaiolo 的帖子非常相似,

现在已经添加了 PropTypes.elementType

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

正如 Ferenc 所提到的,PropTypes.instanceOf(Element)看起来是正确的方法

我检查了以上所有的答案,但我得到了警告的反应,所以我研究了很多,我得到了正确的答案。

import React, { Component } from 'react';


ComponentName.propTypes = {
reference: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.instanceOf(Component) }),
]),
};