javascript - 对合成 onwheel 事件做出反应的上下文 api 状态不持久
问题描述
我正在尝试为轮播实现 onWheel 触发的导航。按钮导航有效,而 onWheel 触发,但不知何故未访问上下文提供程序的初始化状态。任何见解将不胜感激。谢谢你。
上下文提供者:
import CarouselContext from "../context/_carousel"
const CarouselProvider = ({ children }) => {
const [isInitialized, setIsInitialized] = useState(false)
const [carouselLength, setCarouselLength] = useState(0)
const [carouselPosition, setCarouselPosition] = useState(0)
const initializeCarousel = length => {
setCarouselLength(length)
setIsInitialized(true)
console.log(`carouselLength ${carouselLength}`)
}
const nextSlide = () => {
if (carouselPosition === carouselLength) {
setCarouselPosition(0)
} else {
setCarouselPosition(carouselPosition + 1)
}
console.log(`carouselPosition ${carouselPosition}`)
}
const previousSlide = () => {
if (carouselPosition === 0) {
setCarouselPosition(carouselLength)
} else {
setCarouselPosition(carouselPosition - 1)
}
console.log(`carouselPosition ${carouselPosition}`)
}
const state = { carouselLength, carouselPosition, isInitialized }
const methods = { initializeCarousel, nextSlide, previousSlide }
return (
<CarouselContext.Provider value={[state, methods]}>
{children}
</CarouselContext.Provider>
)
}
export default CarouselProvider
轮播结构:
return (
<Page className="works">
<CarouselProvider>
<ScrollNav>
<PreviousWorkButton />
<Carousel>
{works.map((work, index) => (
<CarouselItem key={index}>
<Work project={work} />
</CarouselItem>
))}
</Carousel>
<NextWorkButton />
</ScrollNav>
</CarouselProvider>
</Page>
)
scroll Nav(用于安慰事件被触发,但不显示轮播的当前位置或长度)
const ScrollNav = ({ children }) => {
const [, { nextSlide, previousSlide }] = useContext(CarouselContext)
const delayedScroll = useCallback(
debounce(e => changeNav(e), 500, { leading: true, trailing: false }),
[]
)
const changeNav = direction => {
if (direction === 1) {
nextSlide()
}
if (direction === -1) {
previousSlide()
}
}
const onWheel = e => {
delayedScroll(e.deltaY)
}
return <div onWheel={onWheel}>{children}</div>
}
onclick 按钮触发相同事件,轮播位置和长度保持不变
const NextWorkButton = () => {
const [, { nextSlide }] = useContext(CarouselContext)
const clicked = () => {
nextSlide()
}
return (
<div className="next-work-button">
<button onClick={clicked}>
<DownArrowSvg />
</button>
</div>
)
}
编辑为在提供程序中添加 console.logs,就像在我的本地副本中一样
控制台登录点击事件:
carouselPosition 1
carouselLength 5
控制台登录轮事件(长度不打印):
carouselPosition 0
感谢 kumarmo2,我通过消除去抖动并直接调用事件解决了这个问题。我使用计时器针对车轮事件进行了非常hacky的去抖动。我的解决方案:
const ScrollNav = ({ children }) => {
const [, { nextSlide, previousSlide }] = useContext(CarouselContext)
const [debounce, setDebounce] = useState(false)
const timer = () => {
setTimeout(() => {
setDebounce(false)
}, 1000)
}
const changeNav = e => {
let direction = e.deltaY
if (debounce) {
return
} else if (direction >= 1) {
setDebounce(true)
timer()
nextSlide()
return
} else if (direction <= -1) {
setDebounce(true)
timer()
previousSlide()
return
}
}
return <div onWheel={changeNav}>{children}</div>
}
解决方案
我认为这里发生的事情是,delayedScroll
由于useCallback
. 它“捕获” ,changeNav
而后者又捕获nextSlide
.
所以 nextSlide 将被调用,但由于delayedScroll
useCallback 导致其内部引用未更新,因此您将面临问题。
您可以尝试删除useCallback
anddebounce
一次delayedScroll
吗?如果它有效,将以正确的方式引入去抖动逻辑。
推荐阅读
- ios - H265 编解码器的 iPhone 库中的视频保存错误
- python - Spyder 在 Windows 10 上非常慢
- linkerd - 在链接器中导出没有集群名称的服务
- python - 列表索引必须是整数或切片,而不是 str,同时删除字典中的嵌套键
- iis - IIS SMTP 仅显示一个可供选择的 IP
- scheme - 我可以在主体中间定义一个变量吗?
- laravel - Laravel Blade 和 Vue WPML 字符串翻译
- c# - 我创建了一个索引器并尝试为其设置值,但它一直显示索引超出范围异常
- java - Java 同步帐户示例未按预期工作
- c# - 使用 ef core 和 filehelpers 仅 900 条记录的导入速度变慢