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

React Hooks - Passing ref to child to use ScrollIntoView

我有两个组件。一个 parent 和一个 child.

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

我想我想定义对 childs 按钮 a 的引用,这样我在 parent 按钮 onClick 中可以执行 a:

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

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

这是一个缩小的例子:

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);

我知道上面的代码不起作用,它只是为了说明我正在努力实现的目标。

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

更新

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

以下为其中之一:

Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

解决方案

好的。我想我会 assemble 这里的片段与@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;

编辑 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 导出)。


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

有些东西会导致它无法正常工作。

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

    It seems that your button is also a custom component. Are you sure the ref is being passed to the html button element inside there?

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