React Hooks - 将 ref 传递给 child 以使用 ScrollIntoView [英] React Hooks - Passing ref to child to use ScrollIntoView

查看:91
本文介绍了React Hooks - 将 ref 传递给 child 以使用 ScrollIntoView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

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

这是一个缩小的例子:

ParentComponent.jsx

import React, {useRef} from 'react';从 './ChildComponent' 导入 ChildComponent;const ParentComponent = 道具 =>{const childReference = useRef(null);const onClick = () =>{childReference.scrollIntoView({block: 'end', behavior: 'smooth'});}返回 (<><...一些其他组件><Button onClick={onClick}>点击我转发</Button><ChildComponent ref={childReference}/></>);};

ChildComponent.jsx

从'react'导入React;const ChildComponent = (props, ref) =>{const { 名称、值、描述 } = 道具;返回 (<...一些其他组件><Button ref={ref}>你应该被转发给我</Button>);};ChildComponent.propTypes = {名称:PropTypes.string.isRequired,值:PropTypes.number,描述:PropTypes.string,};ChildComponent.defaultProps = {值:0,描述: '',};导出默认 React.forwardRef(ChildComponent);

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

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

更新

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

以下是其中之一:

<块引用>

不能给函数组件提供引用.尝试访问此引用将失败.你的意思是使用 React.forwardRef() 吗?

解决方案

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

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

ParentComponent.jsx

import React, { useRef } from 'react';从 './ChildComponent' 导入 ChildComponent;const ParentComponent = 道具 =>{const childReference = useRef(null);const scrollIntoView = () =>{childReference.current.scrollIntoView({block: 'center', inline: 'center', behavior: 'smooth'});}返回 (<><...一些其他组件><Button onClick={scrollIntoView}>点击我转发</Button><ChildComponent ref={childReference}</>);};导出默认父组件;

ChildComponent.jsx

import React, {forwardRef} from 'react';从 'prop-types' 导入 PropTypes;const ChildComponent = forwardRef((props, ref) => {const { 名称、值、描述 } = 道具;返回(<><...一些其他组件><Button ref={ref}>你应该被转发给我</Button></>);});ChildComponent.propTypes = {名称:PropTypes.string.isRequired,值:PropTypes.number,描述:PropTypes.string,};ChildComponent.defaultProps = {值:0,描述: '',};导出默认子组件;

解决方案

Edit 2:

我猜你正在做类似的事情

const ChildComponent = (props, ref) =>{ ... }ChildComponent.propTypes = { ... }导出默认 React.forwardRef(ChildComponent)

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

const ChildComponent = (props, ref) =>{ ... }const ForwardComponent = React.forwardRef(ChildComponent)ForwardComponent.propTypes = { ... }导出默认 ForwardComponent

更好的方法是

//使用 forwarRefconst ChildComponent = React.forwarRef((props, ref) => {const { 名称、值、描述 } = 道具;返回 (<...一些其他组件><Button ref={ref}>你应该被转发给我</Button>);});

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

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

你应该添加

导出默认 React.forwardRef(ChildComponent)

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

<小时>

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

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

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

    看来你的按钮也是自定义组件.你确定 ref 被传递给里面的 html button 元素吗?

  3. 要使用功能组件的第二个参数,您应该使用 React.forwardRef.例如导出默认 React.forwardRef(ChildComponent)

I have two components. A parent and a child.

Inside the parent component I have a button. If the user clicks on that button I want to do a ScrollIntoView to another button inside the child component.

I guess I want to define a reference to the childs button a so that I inside the parent button onClick can do a:

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

that will scroll to the button in the child component.

Here is a minified example:

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

I know the above code doesn't work, it was just to illustrate what I am trying to achieve.

I have really tried every other solution I have been able to find by Googling and they all seem so easy, but none of them seem to work for my use case. I have tried using forwardRef as well, but that also doesn't fix it for me.

UPDATE

I guess I was a little vague on what's not working. I've been getting a lot of different error messages with the implementation.

The following is one of them:

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

Solution

Okay. I thought I'd assemble the pieces here with the solution provided by @Vencovsky.

This is the full implementation with the two example components seen in the question:

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;

解决方案

Edit 2:

I guess you are doing something like

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

ChildComponent.propTypes = { ... }

export default React.forwardRef(ChildComponent)

But what you need to do is pass propTypes after React.forwardRef, like so:

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

const ForwardComponent = React.forwardRef(ChildComponent)

ForwardComponent.propTypes = { ... }

export default ForwardComponent

A better way to do it would be like

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

Then you wouldn't need to change propTypes and create another component.

Edit:

As your Edit, I can see that you forgot to use React.forwardRef.

You should add

export default React.forwardRef(ChildComponent)

To your ChildComponent file (export it with forwardRef).


What is not working? Are you getting an error? You should explain better what is going on, but I will try to guess.

There is somethings that can make it not work.

  1. You need to use ref.current.foo instead of ref.foo
  2. As @JeroenWienk said:

    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. To use the second parameter of an functional component, you should be using React.forwardRef. e.g. export default React.forwardRef(ChildComponent)

这篇关于React Hooks - 将 ref 传递给 child 以使用 ScrollIntoView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆