PanResponder中state值递增异常:首次滑动更新后后续无变化
问题原因与解决方案
这个问题是闭包陷阱导致的:
- 你用
useRef创建panResponderLeft时,PanResponder.create仅在组件首次渲染时执行一次,此时回调函数里的currentIndex捕获的是初始值0。 - 第一次调用
setCurrentIndex(currentIndex+1)后,currentIndex更新为1,但panResponderLeft里的回调仍引用旧闭包中的currentIndex(值为0),后续滑动时执行的是setCurrentIndex(0+1),相当于把currentIndex重新设为1,看起来就没有变化了。
解决方法
使用函数式更新修改state,函数式更新会接收当前最新的state值作为参数,彻底避开闭包问题:
const [currentIndex, setCurrentIndex] = useState(0) const panResponderLeft = useRef( PanResponder.create({ onStartShouldSetPanResponder: () => true, onPanResponderMove: (_, gestureState) => { updateLeftPosition(gestureState.dx); }, onPanResponderRelease: (_, gestureState) => { if (gestureState.dx > 50) { // 函数式更新,获取最新的currentIndex setCurrentIndex(prevIndex => prevIndex + 1) } }, }), ).current;
如果你的updateLeftPosition也依赖最新的state或props,同样要注意闭包问题,必要时可以用useCallback包裹该函数,或者在依赖变化时重新创建PanResponder(比如将PanResponder.create放在useEffect中,添加对应依赖项),不过函数式更新是最简洁的解决方案。
内容的提问来源于stack exchange,提问作者Bryl
相关产品推荐
相关产品推荐

