小编典典

React中引用的正确原型是什么?

reactjs

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

存储的ref如下所示:

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

此引用的正确propType是什么?


阅读 328

收藏
2020-07-22

共1个答案

小编典典

TL; DR

如果您想要输入仅需要本机DOM元素(例如adiv或an)的引用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指向的东西,它将使用redux从redux传递mapStateToProps。DOM元素的道具类型为:(myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element)如果它是DOM元素)。虽然,我会:

  1. 将其重命名为myElementToBePutInReduxGlobalStore(元素不是引用)
  2. 避免在Redux存储中存储不可序列化的数据
  3. 避免像React工程师Seb Markbage所述在道具中传递元素

对实际问题的长答案

问:React中引用的正确原型是什么?

用例示例:

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中存在两种引用:

  1. 看起来像这样的对象:{ current: [something] },通常由React.createRef()助手或React.useRef()钩子创建
  2. 一个回调函数,将[something]其作为参数接收(如OP示例中的一个)

注意:从历史上看,您也可以使用字符串ref,但是 它被认为是旧式的,因此会从react中删除

第二项是很简单,需要以下道具类型:PropTypes.func

第一个选项不太明显,因为您可能要指定ref指向的元素的类型。

很多好的答案

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

如果要完全灵活:

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

上面只是强制了带有current属性的对象ref的形状。对于任何类型的参考,它都将始终工作。出于使用prop类型的目的(这是 在开发时
发现任何不一致之处的一种方式),这可能就足够了。具有shape的对象并传递给prop 似乎 不太可能 不是 实际的引用。{ current: [any] }``refToForward __

但是 ,您可能希望声明您的组件不希望 任何 类型的引用,而只是希望某种类型,只要它需要该引用即可。

我已经设置了一个沙箱,展示了几种声明ref的不同方法,甚至包括一些非常规的方法,然后使用许多prop类型对其进行测试。
你可以在这里找到它


如果只希望引用指向本机输入元素,而不是 任何 HTML Element

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

如果只希望引用指向React类组件:

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

如果只希望引用指向功能组件的refuseImperativeHandle公开一些公共方法:

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

注意:上面的prop类型很有趣,因为它还涵盖了react组件和本机DOM元素,因为它们都继承了基本的javascriptObject


没有一种好的方法可以为引用声明prop类型,这取决于用法。
如果您的参考指向非常明确的东西,那么值得添加特定的道具类型。否则,仅检查一般形状就足够了。


关于服务器端渲染的注意事项

如果您的代码必须在服务器上运行,除非您已经使用polyfill DOM环境,否则NodeJS
Element中将包含任何其他客户端类型undefined。您可以使用以下填充程序来支持它:

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

以下React Docs页面提供了有关如何使用ref的更多见解,包括对象和回调,以及如何使用useRef钩子

感谢@Rahul Sagore,@ Ferenk Kamra,@ svnm和@Kamuela Franco来更新答案

2020-07-22