React native setState挂钩未更新-尽管prevState显示正确的值

React native setState挂钩未更新-尽管prevState显示正确的值,react-native,react-hooks,expo,webhooks,React Native,React Hooks,Expo,Webhooks,我正在使用state变量跟踪我以前的状态 动画可以工作(没有索引),但是当我工作时 const [index, setIndex] = useState(0) useEffect(() => { animation.addListener((scroll) => { setTimeout(function() { let position = Math.floor(scroll.value / cardWidt

我正在使用state变量跟踪我以前的状态

动画可以工作(没有索引),但是当我工作时

const [index, setIndex] = useState(0)

useEffect(() => {
        animation.addListener((scroll) => {
            setTimeout(function() {
                let position = Math.floor(scroll.value / cardWidth + 0.75);
                if (position >= restaurants.length - 1) position = restaurants.length - 1;
                if (position <= 0) position = 0;

                console.log("position: ", position, "index: ", index)

                if (index !== position) {
                    setIndex(prevState => {
                        console.log("previous: ", prevState, "position: ", position, "index: ", index)
                        return position
                    });
                    const { coordinate } = restaurants[position];
                    mapRef.current.animateCamera({
                        center: {
                            latitude: coordinate.latitude,
                            longitude: coordinate.longitude,
                        },
                         altitude: 2000, // zooms in when viewing specific location
                    }, {duration: 1000}) // not sure if duration is actually doing anything
                }
            }, 3000);
        });
        return function cleanUp(): void { animation.removeAllListeners(); }
    }, []);
编辑:我找到的答案


正如许多人在下面所述,useState是异步的,将在更新之前等待函数结束。侦听器是一个在激活后一直运行到下一次渲染的函数。因此,值仅在重新渲染时更新。我决定切换到useRef,因为它是同步的,允许我在不重新渲染的情况下保持最新的值。

正确,原因如下:

  • addListener
    中创建一个闭包,捕获
    索引的初始值,该值通过
    useState(0)
    设置为
    0
  • 您为
    useffect
    提供了一个空的依赖项列表,这意味着当组件装载时,它将只运行一次
要修复它,您应该向
useffect
的依赖项列表提供
index
,以允许它重新运行,从而获取最新的
索引

useffect(()=>{…},[index]);
或者,如果您发现取消勾选/重新勾选事件处理程序有问题,您可以将一个函数传递到
setIndex
,该函数允许您访问以前的值,例如

setIndex(旧索引=>{
设newIndex=oldIndex;
如果(旧索引!=位置){
//更新新索引
}
返回新索引;
});
position:  1 index:  0
previous:  1 position:  1 index:  0
position:  1 index:  0
previous:  1 position:  1 index:  0
position:  1 index:  0
previous:  1 position:  1 index:  0
position:  1 index:  0
previous:  2 position:  2 index:  0
position:  2 index:  0
previous:  2 position:  2 index:  0
position:  2 index:  0
previous:  3 position:  3 index:  0
position:  3 index:  0
previous:  3 position:  3 index:  0
position:  3 index:  0