【发布时间】:2021-06-30 05:33:43
【问题描述】:
TL;DR:转到react code sandbox 并尝试单击任一按钮几次。 Buggy 没有到达幻灯片的结尾。
我正在制作一个水平滚动的幻灯片。
它由一个带有overflow: auto 的容器 组成,其中包含一个水平溢出它的track。每个 slide 都是 track 的子级,并且与视口一样宽。 容器有一个索引状态,表示哪个幻灯片在视图中:
const slides = [/* some array of json data */]
const [index, setIndex] = useState(0)
const track = useRef(null)
const container = useRef(null)
return (
<div ref={container} onScroll={onScroll}>
<div ref={track}>
{slides.map(() => (
<div></div>
))}
</div>
</div>
)
要跟踪查看的幻灯片,有一个onScroll 函数:
const onScroll = () => {
const newIndex = // math to get index from DOM
if (index !== newIndex)
setIndex(newIndex)
}
还有一个onClick 功能允许用户自动滚动到下一张幻灯片:
const onClick = () => {
track.current.children[index + 1].scrollIntoView({
behavior: "smooth"
})
}
这个onClick 被传递给一个按钮组件:
const BuggyButton = ({ disabled, onClick }) => (
<button type="button" disabled={disabled} onClick={onClick}>
click me
</button>
)
当用户到达最后一张幻灯片时,按钮被禁用:
<BuggyButton onClick={onClick} disabled={index === slides.length - 1} />
问题:一旦<BuggyButton/> 被禁用,scrollIntoView 就会停止(过早地)。 为什么会这样?
这是在代码沙箱中完全重现和简化的问题:https://codesandbox.io/s/disable-button-cancels-scroll-270hz?file=/src/App.js
这里尽可能接近在 vanilla JS 中重现该问题:https://codesandbox.io/s/disable-button-cancels-scroll-vanilla-018mb
如果您只是在寻找解决方案(而不是想了解正在发生的事情,代码沙箱中有一个 <ProperButton/> 组件可以正常工作。带着这个问题,我试图了解 什么反应在幕后会导致浏览器中断滚动并保持其位置而不是将其重置为零。
【问题讨论】:
-
只需将 BuggyButton 放在 App 内
-
@ludwiguer 我希望了解为什么这是一个问题,而不是如何解决它。此外,在真实的代码库中,我将拥有一个更复杂的按钮组件,我不能只在另一个组件的
render中声明它。 -
@ludwiguer 然而,有趣的是,它在 App 内部而不是外部声明时有效。知道为什么吗?
标签: javascript reactjs