reactjs - 有没有更好的方法从子组件调用 ref.current.scrollIntoView() 以滚动到其父组件中的 ref?
问题描述
我正在开发我的第一个 ReactJS/TypeScript 项目。
我要做的就是ref.current.scrollIntoView()
从子组件调用以滚动到其父组件中的引用。
我已经在onClick
处理程序中使用了一个相当丑陋的 if 语句来让它工作scrollTest()
,以保持 TypeScript 的快乐。希望有一种更清洁的方法来做到这一点。
如果有办法避免Sections.displayname
明确设置,则可以加分。
import {
Container,
Grid,
Link,
Typography
} from '@material-ui/core'
import React, { ReactElement } from 'react'
const Section = (
{
children
}: {
children: React.ReactNode
}
): ReactElement => {
return(
<>
<Grid container style={{minHeight: "100vh"}}>
<Grid item>
{children}
</Grid>
</Grid>
</>
)
}
const Sections = React.forwardRef<HTMLElement>((_, ref): ReactElement => {
const scrollTest = (): void => {
if (ref && "current" in ref && ref.current) {
ref.current.scrollIntoView()
}
}
const sections = [
<>
<Typography paragraph variant="h3">
<Link onClick={scrollTest}>Scroll to footer</Link>
</Typography>
</>
].map((section, index) => {
return(
<Section key={index}>
{section}
</Section>
)
})
return(<>{sections}</>)
})
Sections.displayName = 'Sections'
export default function Test(): ReactElement {
const footerRef = React.useRef<HTMLElement>(null)
return (
<>
<Container>
<Sections ref={footerRef} />
<Grid
component="footer"
container
ref={footerRef}
>
<Grid>
<Typography paragraph>
Footer
</Typography>
</Grid>
</Grid>
</Container>
</>
)
}
解决方案
根据 jtbandes 的评论,我得到以下信息:
import {
Container,
Grid,
Link,
Typography
} from '@material-ui/core'
import React, { ReactElement } from 'react'
const Section = (
{
children
}: {
children: React.ReactNode
}
): ReactElement => {
return(
<>
<Grid container style={{minHeight: "100vh"}}>
<Grid item>
{children}
</Grid>
</Grid>
</>
)
}
const Sections = (
{
footerRef
}: {
footerRef: React.RefObject<HTMLElement>
}
): ReactElement => {
const scrollToFooter = (): void => {
footerRef?.current?.scrollIntoView()
}
const sections = [
<>
<Typography paragraph variant="h3">
<Link onClick={scrollToFooter}>Scroll to footer</Link>
</Typography>
</>
].map((section, index) => {
return(
<Section key={index}>
{section}
</Section>
)
})
return(<>{sections}</>)
}
export default function Test(): ReactElement {
const footerRef = React.useRef<HTMLElement>(null)
return (
<>
<Container>
<Sections footerRef={footerRef} />
<Grid
component="footer"
container
ref={footerRef}
>
<Grid>
<Typography paragraph>
Footer
</Typography>
</Grid>
</Grid>
</Container>
</>
)
}
不知道为什么,但没有forwardRef()
安全运算符 ,?
现在可以同时使用RefObject
和current
使if
语句变得多余。
删除forwardRef()
也消除了displayname
明确设置,给予奖励积分的需要。
考虑了 Dennis Matinez 的建议,但将点击处理程序与点击事件的源放在同一组件中对我来说更有意义。
推荐阅读
- python - **不能**通过 selenium 使用以下代码点击与 href="#"
- html - 如何通过在 vue.js 中使用 flex 在两个内容之间提供空间?
- api - 前端和后端之间如何使用 tsl 进行通信?
- woocommerce - 如何在结帐woocommerce中更改特定产品的条带中的capture_method
- python - 当所有参与者的数据都放在一起时,我该如何分离参与者的数据?
- r - 找到每 n 个。数据帧中的最大值和所属信息
- flutter - 为什么我在此应用程序的编译时收到 RangeError?
- .net - 处理 PostgreSQL 事务中的并发性
- python - 虚拟助手程序:Python 无法找到变量
- c# - C# - PowerShell 对象不执行 Remove-AppxPackage