From hooks like useState(x) from React, or useValue(x) from Redash, I am used to the behavior that if x changes, the return value of the hook stays the same unless I manipulate the value afterwards (e.g using setState/setValue)
When the x in const val = useDerivedValue(x) changes, I was surprised to see that the Shared Value updates too.
I'm led to believe that this is a bug. Could it be?
Repro:
import React, {useState} from 'react';
import {Button, StyleSheet, View} from 'react-native';
import {useSharedValue} from 'react-native-reanimated';
const styles = StyleSheet.create({
centered: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
},
});
export const StartScreen = () => {
const [x, setX] = useState(0);
const val = useSharedValue(x);
console.log(val.value);
// After pressed the button, the shared value has changed
// without `val.value = 1` ever being called
return (
<View style={styles.centered}>
<Button title="Press me" onPress={() => setX(1)} />
</View>
);
};
I see your point, it is not a bug, just a matter of approach(by saying that I mean we did it that way consciously).
You're right that a result of useState changes only when triggered explicitly.
Adding such functionality is very easy, we could also go for conditional change on rerender. We're going to discuss it, thanks!
I use this hook as a workaround for now:
export function useSharedValue<T>(value: T, shouldRebuild = false) {
const ref = useRef<T | null>(null);
if (ref.current === null || shouldRebuild) {
ref.current = value;
}
return REAuseSharedValue(ref.current);
}
Thanks a lot for considering to change it!
What I think would be the advantage of memoizing it is that you can yourself change the shared value in an effect and also wrap it in a withTiming or withSpring function, and with that easily achieve a transition effect when a prop is changing.
@terrysahaidak's workaround works great as well, thanks a lot!
Most helpful comment
I use this hook as a workaround for now: