React Hooks - 将 ref 传递给子级以使用 ScrollIntoView

Posted

技术标签:

【中文标题】React Hooks - 将 ref 传递给子级以使用 ScrollIntoView【英文标题】:React Hooks - Passing ref to child to use ScrollIntoView 【发布时间】:2020-03-27 06:18:33 【问题描述】:

我有两个组件。父母和孩子。

在父组件内部我有一个按钮。如果用户单击该按钮,我想对子组件内的另一个按钮执行 ScrollIntoView。

我想我想定义一个对子按钮 a 的引用,以便我在父按钮 onClick 内可以执行以下操作:

ref.scrollIntoView(block: 'end', behavior: 'smooth');

这将滚动到子组件中的按钮。

这是一个缩小的例子:

ParentComponent.jsx

import React, useRef from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = props => 
  const childReference = useRef(null);

  const onClick = () => 
    childReference.scrollIntoView(block: 'end', behavior: 'smooth');
  

  return (
    <>
      <...some other components>
      <Button onClick=onClick>Click me to be forwarded</Button>
      <ChildComponent ref=childReference/>
    </>
  );
;

ChildComponent.jsx

import React from 'react';

const ChildComponent = (props, ref) => 

  const  name, value, description  = props;

  return (
    <...some other components>
    <Button ref=ref>You should be forwarded to me</Button>
  );
;

ChildComponent.propTypes = 
  name: PropTypes.string.isRequired,
  value: PropTypes.number,
  description: PropTypes.string,
;

ChildComponent.defaultProps = 
  value: 0,
  description: '',
;

export default React.forwardRef(ChildComponent);

我知道上面的代码不起作用,只是为了说明我想要实现的目标。

我真的尝试了通过谷歌搜索找到的所有其他解决方案,它们看起来都很简单,但它们似乎都不适用于我的用例。我也尝试过使用 forwardRef,但这也不能解决我的问题。

更新

我想我对什么不起作用有点含糊。我在执行过程中收到了很多不同的错误消息。

以下是其中之一:

函数组件不能被赋予 refs。尝试访问此 ref 将失败。你的意思是使用 React.forwardRef() 吗?

解决方案

好的。我想我会用@Vencovsky 提供的解决方案在这里组装这些部分。

这是问题中的两个示例组件的完整实现:​​

ParentComponent.jsx

import React,  useRef  from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = props => 
  const childReference = useRef(null);

  const scrollIntoView = () => 
    childReference.current.scrollIntoView(block: 'center', inline: 'center', behavior: 'smooth');
  

  return (
    <>
    <...some other component>
    <Button onClick=scrollIntoView>Click me to be forwarded</Button>
    <ChildComponent ref=childReference
    </>
  );
;

export default ParentComponent;

ChildComponent.jsx

import React, forwardRef from 'react';
import PropTypes from 'prop-types';

const ChildComponent = forwardRef((props, ref) => 
  const  name, value, description  = props;

  return(
    <>
      <...some other components>
      <Button ref=ref>You should be forwarded to me</Button>
    </>
  );
);

ChildComponent.propTypes = 
  name: PropTypes.string.isRequired,
  value: PropTypes.number,
  description: PropTypes.string,
;

ChildComponent.defaultProps = 
  value: 0,
  description: '',
;

export default ChildComponent;

【问题讨论】:

看来你的按钮也是自定义组件。您确定将 ref 传递给那里的 html 按钮元素吗? @JeroenWienk。这实际上是一个很好的建议。我想我应该先尝试一个基本的 HTML5 按钮,如果可行,我当然也应该更新我的自定义 Button 【参考方案1】:

编辑 2:

我猜你正在做类似的事情

const ChildComponent = (props, ref) =>  ... 

ChildComponent.propTypes =  ... 

export default React.forwardRef(ChildComponent)

但是你需要做的是在React.forwardRef之后传递propTypes,就像这样:

const ChildComponent = (props, ref) =>  ...           

const ForwardComponent = React.forwardRef(ChildComponent)

ForwardComponent.propTypes =  ... 

export default ForwardComponent

更好的方法是

//                     using forwarRef
const ChildComponent = React.forwarRef((props, ref) => 

  const  name, value, description  = props;

  return (
    <...some other components>
    <Button ref=ref>You should be forwarded to me</Button>
  );
);

那么您就不需要更改propTypes 并创建另一个组件。

编辑:

作为您的编辑,我可以看到您忘记使用React.forwardRef

你应该添加

export default React.forwardRef(ChildComponent)

到您的 ChildComponent 文件(使用 forwardRef 导出)。


什么不工作?你有错误吗?您应该更好地解释发生了什么,但我会尝试猜测。

有些东西可以使它不起作用。

    您需要使用ref.current.foo 而不是ref.foo 正如@JeroenWienk 所说:

    看来您的按钮也是一个自定义组件。您确定将 ref 传递给那里的 html 按钮元素吗?

    要使用功能组件的第二个参数,您应该使用React.forwardRef。例如export default React.forwardRef(ChildComponent)

【讨论】:

谢谢。这让我在某种程度上朝着正确的方向前进。但是我现在收到了这个警告Warning: forwardRef render functions do not support propTypes or defaultProps. Did you accidentally pass a React component? 如果我不应该 forwardRef 一个 React 组件,那么它应该如何使用? @Zeliax 请在您的问题中添加您如何使用propTypes/defaultPropsforwardRef。我想我知道如何解决这个问题,但是如果您添加它,我可以更加确定。我也会编辑我的问题,所以请多多关照。 我已经更新了我的代码,以类似于我实际实现的。 scrollIntoView 现在可以工作了,摆脱错误会很高兴。 @Zeliax get rid of the error 你的意思是警告吗?只需检查我的编辑,现在它应该可以正常工作了。 没关系。我看到你更新了! :D 谢谢。你是救生员;)

以上是关于React Hooks - 将 ref 传递给子级以使用 ScrollIntoView的主要内容,如果未能解决你的问题,请参考以下文章

在 React-Router 中将状态作为道具从父级传递给子级?

React,将在父级创建的引用传递给子级

使用 XLPagerTabStrip 将数据从父级传递给子级

如何通过事件将数据从父级传递给子级

Vue 组件:如何将数据从父级传递给子级

React学习笔记 Redux