I am getting different behavior between the two code blocks when I believe they should be the same. My goal is to update compass heading using watchHeadingAsync and perform and animation from the previous heading to the new heading.
The first code block results in heading[0] always being 0 and heading[1] being the current heading. The second block performs as expected. Is there some race condition I am unaware of that is causing this? Any insight would be greatly appreciated!
const [heading, setHeading] = useState([0,0]);
useEffect(() => {
Location.watchHeadingAsync((headObj) => {
let h = Math.round(headObj.magHeading) * -1;
setHeading([heading[1], h]);
});
}, []);
console.log(heading[0], '->', heading[1]);
const [heading, setHeading] = useState([0,0]);
const oldHeading = useRef(0);
const newHeading = useRef(0);
useEffect(() => {
Location.watchHeadingAsync((headObj) => {
let h = Math.round(headObj.magHeading) * -1;
oldHeading.current = newHeading.current;
newHeading.current = h;
setHeading([oldHeading.current, newHeading.current]);
});
}, []);
console.log(heading[0], '->', heading[1]);
The
headingvariable inside theuseEffectcallback is the constant value from when the effect ran. Indeed, it's always[0, 0]and never changes. To fix this stale closure problem, you want to use the updater callback variant of the state setter:Do not use refs as a workaround for this.