React中useEffect的setInterval里useRef值始终为0的问题
React水平滚动文本组件ref值始终为0的问题解决
问题根源
- ref未同步state更新:你定义的
contendWidthRef(注意拼写错误,应为contentWidthRef)初始值绑定了contentWidth的初始值0,但contentWidth通过onContentSizeChange更新后,ref的.current不会自动同步这个变化,导致它一直保持0。 - 位置ref未实时更新:
currentPositionRef只在计算时做了累加,但没有把setCurrentPosition后的新值同步回ref,同时因为contendWidthRef一直是0,每次累加后的position都会触发position > 0的判断,立刻将滚动位置重置为0,看起来就像ref值始终为0。
修正后的代码
const SiteAlert = () => { const [contentWidth, setContentWidth] = React.useState(0); const scrollViewRef = React.useRef(); const currentPositionRef = React.useRef(0); const contentWidthRef = React.useRef(0); // 修正拼写错误 // 监听contentWidth变化,同步更新ref React.useEffect(() => { contentWidthRef.current = contentWidth; }, [contentWidth]); React.useEffect(() => { function handleScroll() { currentPositionRef.current += 5; const position = currentPositionRef.current; if (position > contentWidthRef.current) { currentPositionRef.current = 0; scrollViewRef.current?.scrollTo({ x: 0, animated: true }); } else { scrollViewRef.current?.scrollTo({ x: position, animated: true }); } } const activeInterval = setInterval(handleScroll, 400); return () => clearInterval(activeInterval); }, []); return ( <ScrollView ref={scrollViewRef} horizontal bounces style={styles.siteAlert} onContentSizeChange={(width) => setContentWidth(width)} > <Text style={styles.text} numberOfLines={1}> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod in cupiditate, expedita soluta est earum quaerat adipisci fugit, atque, eveniet maxime sint eligendi voluptatem minus dolore et tenetur aliquid totam! Error suscipit aliquam impedit ratione veritatis, placeat sapiente ab consequatur? </Text> </ScrollView> ); };
关键修改说明
- 修正了
contendWidthRef的拼写错误,改为contentWidthRef。 - 添加了专门的
useEffect监听contentWidth的变化,实时将最新的内容宽度同步到contentWidthRef.current。 - 直接用
currentPositionRef管理滚动位置,不再依赖state,避免闭包导致的旧值问题,同时每次更新位置后直接同步ref,确保下次计算基于最新值。 - 移除了不必要的
_currentPositionstate,因为用ref管理滚动位置更适合这种定时更新的场景。
内容的提问来源于stack exchange,提问作者Gh05d
相关产品推荐
相关产品推荐

