我实现了一个项目列表中的键盘键或按钮导航。在本地我没有得到任何错误,在构建阶段我得到了以下错误:
Error: React Hook "useRef" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks
Error: React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks
Error: React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks
这是我的代码:
'use client'
import { FixedSizeList } from 'react-window'
import useIsMobile from '../../../../../hooks/useIsMobile'
import PackagesCard from './packagesCard'
import AutoSizer from 'react-virtualized-auto-sizer'
import { useRef, useState, useEffect } from 'react'
import Image from 'next/image'
const VirtualPackagesCarousel = ({ data }) => {
const { mobile } = useIsMobile()
if (!data || data.length === 0) {
return (
<div className="h-[350px] flex text-neutrals-50 justify-center align-middle">
There are no courses here yet!
</div>
)
}
const listRef = useRef(null)
const [selection, setSelection] = useState(null)
const handleKeyDown = (e) => {
if (e.key === 'ArrowRight') {
e.preventDefault()
if (selection === null) {
setSelection(0)
} else {
setSelection(Math.min(data.length - 1, selection + 1))
}
}
if (e.key === 'ArrowLeft') {
e.preventDefault()
if (selection === null) {
setSelection(0)
} else {
setSelection(Math.max(0, selection - 1))
}
}
}
const handleNext = () => {
if (selection === null) {
setSelection(0)
} else {
setSelection(Math.min(data.length - 1, selection + 1))
}
}
const handleBack = () => {
if (selection === null) {
setSelection(0)
} else {
setSelection((prev) => Math.max(0, prev - 1))
}
}
const handleBlur = () => {
setSelection(null)
}
useEffect(() => {
const list = listRef.current
if (!list) return
if (selection === null) return
list.scrollToItem(selection)
}, [selection])
return (
<div
tabIndex={0}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
className="w-full flex flex-col gap-5 outline-none border-transparent focus:border-transparent focus:ring-0"
>
<div className="flex gap-3 justify-end visible mobile:invisible">
<Image
src="/images/arrowLeft.svg"
alt="arrowBack"
width="10"
height="10"
className="cursor-pointer invert"
onClick={handleBack}
/>
<Image
src="/images/arrowRight.svg"
alt="arrowNext"
width="10"
height="10"
className="cursor-pointer invert "
onClick={handleNext}
/>
</div>
<AutoSizer>
{({ _, width }) => (
<FixedSizeList
height={400}
itemCount={data.length}
itemSize={mobile ? 300 : 600}
width={width}
layout="horizontal"
ref={listRef}
className="outline-none border-transparent focus:border-transparent focus:ring-0"
>
{({ index, style }) => (
<div className="px-2.5 mobile:px-1" style={style}>
<PackagesCard
data={data[index]}
key={data[index].id}
index={index}
setSelection={setSelection}
selection={selection}
/>
</div>
)}
</FixedSizeList>
)}
</AutoSizer>
</div>
)
}
export default VirtualPackagesCarousel
我不知道我哪里出错了,有人能帮我弄清楚错误在哪里吗?为什么我在本地没有收到这些错误,而在构建阶段却收到了?
1条答案
按热度按时间bvuwiixz1#
将第一个
if
语句移到所有钩子调用之后。参见Rules of Hooks。只要渲染器之间的Hook调用顺序相同,React就可以将某些本地状态与每个渲染器关联起来。