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
/defaultProps
和forwardRef
。我想我知道如何解决这个问题,但是如果您添加它,我可以更加确定。我也会编辑我的问题,所以请多多关照。
我已经更新了我的代码,以类似于我实际实现的。 scrollIntoView 现在可以工作了,摆脱错误会很高兴。
@Zeliax get rid of the error
你的意思是警告吗?只需检查我的编辑,现在它应该可以正常工作了。
没关系。我看到你更新了! :D 谢谢。你是救生员;)以上是关于React Hooks - 将 ref 传递给子级以使用 ScrollIntoView的主要内容,如果未能解决你的问题,请参考以下文章
在 React-Router 中将状态作为道具从父级传递给子级?