reactjs - Typescript 滚动窗口函数类型
问题描述
我正在尝试制作一个允许用户将窗口滚动到屏幕顶部的 React 组件。我已经设置了组件和类型,但是在设置窗口的属性时遇到了问题。我目前的错误是这样的:
元素隐式具有“任何”类型,因为索引表达式不是“数字”类型。
如何正确处理窗户?
import { throttle } from 'lodash'
import React, { useState } from 'react'
import { useEventListener } from '../../hooks'
import { Arrow } from './styles'
interface ScrollRest {
showBelow: number,
className: string,
size: string
}
interface ScrollProps {
direction: string,
by: number,
to: number,
rest: ScrollRest
}
interface ScrollFunctionProps {
mode: string,
to: number
}
export default function Scroll( { direction = `up`, by, to, rest }: ScrollProps ) {
const { showBelow, className, size = `calc(0.6em + 30px)` } = rest
if ( ![`up`, `down`].includes( direction ) )
throw TypeError(
`Scroll component's direction prop must be either 'up' or 'down'`
)
if ( to && ( typeof to !== `number` || to <= 0 ) )
throw TypeError( `Scroll component's to prop must be a positive number` )
if ( by && typeof by !== `number` )
throw TypeError( `Scroll component's by prop must be a number` )
const [show, setShow] = useState( showBelow ? false : true )
const scroll = ( { mode, to }: ScrollFunctionProps ) =>
window[`scroll` + mode]( { top: to, behavior: `smooth` } ) // <- Error here!
const handleScroll = throttle( () => {
if ( !showBelow ) return
if ( window.scrollY > showBelow ) {
if ( !show ) setShow( true )
} else {
if ( show ) setShow( false )
}
}, 300 )
useEventListener( `scroll`, handleScroll )
const handleClick = () => {
if ( to ) scroll( { mode: `To`, to: to * window.innerHeight } )
else if ( by ) scroll( { mode: `By`, to: by * window.innerHeight } )
else if ( direction === `up` ) scroll( { mode: `To`, to: 0 } )
else scroll( { mode: `To`, to: document.body.scrollHeight } )
}
const arrowProps = { show, direction, className, size }
return <Arrow onClick={handleClick} {...arrowProps} />
}
解决方案
最简单的更改是将mode
类型限制为'scrollTo' | 'scrollBy'
方法名称:
interface ScrollFunctionProps {
mode: 'scrollTo' | 'scrollBy',
to: number
}
这允许 TypeScript 正确推断window.scrollXXX(...)
方法调用的类型签名。
import { throttle } from 'lodash'
import React, { useState } from 'react'
import { useEventListener } from '../../hooks'
import { Arrow } from './styles'
interface ScrollRest {
showBelow: number,
className: string,
size: string
}
interface ScrollProps {
direction: string,
by: number,
to: number,
rest: ScrollRest
}
interface ScrollFunctionProps {
mode: 'scrollTo' | 'scrollBy', // restrict `mode` to known Window scroll method names
to: number
}
export default function Scroll( { direction = `up`, by, to, rest }: ScrollProps ) {
const { showBelow, className, size = `calc(0.6em + 30px)` } = rest
if ( ![`up`, `down`].includes( direction ) )
throw TypeError(
`Scroll component's direction prop must be either 'up' or 'down'`
)
if ( to && ( typeof to !== `number` || to <= 0 ) )
throw TypeError( `Scroll component's to prop must be a positive number` )
if ( by && typeof by !== `number` )
throw TypeError( `Scroll component's by prop must be a number` )
const [show, setShow] = useState( showBelow ? false : true )
const scroll = ( { mode, to }: ScrollFunctionProps ) =>
window[mode]( { top: to, behavior: `smooth` } )
const handleScroll = throttle( () => {
if ( !showBelow ) return
if ( window.scrollY > showBelow ) {
if ( !show ) setShow( true )
} else {
if ( show ) setShow( false )
}
}, 300 )
useEventListener( `scroll`, handleScroll )
const handleClick = () => {
if ( to ) scroll( { mode: `scrollTo`, to: to * window.innerHeight } )
else if ( by ) scroll( { mode: `scrollBy`, to: by * window.innerHeight } )
else if ( direction === `up` ) scroll( { mode: `scrollTo`, to: 0 } )
else scroll( { mode: `scrollTo`, to: document.body.scrollHeight } )
}
const arrowProps = { show, direction, className, size }
return <Arrow onClick={handleClick} {...arrowProps} />
}
推荐阅读
- c - c char 数组到 uint8_t 数组
- java - spring boot 应用程序重新启动并显示消息“Tomcat 已启动”
- node.js - Passport local auth plus passport mongoose local 不接受电子邮件作为用户名
- vb.net - VB.NET OverflowException 非常小的操作
- c# - C# - 尝试用另一个 XmlNode 替换 XmlNode 时出现异常
- python - 字典更新序列元素#0的长度为1;加载页面时需要2
- php - 如何在 Wordpress 中添加具有多个值的短代码属性?
- c# - C#“无法建立连接,因为目标机器主动拒绝它”
- c# - 使用消息安全和客户端凭据类型“Windows”的 Docker 容器内的 WCF
- git - git FETCH_HEAD 短期参考