How do i trigger a useEffect based on a sharedValue from the Reanimated libary
M

3

6

How do i trigger a useEffect based on a sharedValue from the Reanimated libary?

 const sharedValue = useSharedValue(0);
  useEffect(() => {
    console.log("exectue functions");
  }, [sharedValue.value]);

Is there a best practice for this. Or is there another way to trigger functions (sync and async) based on a change in a sharedValue.

Maryland answered 22/9, 2022 at 12:18 Comment(0)
M
13

You can use:

  1. useAnimatedReaction;
  2. useDerivedValue;

Solution with useAnimatedReaction

const sharedValue = useSharedValue(0);

useAnimatedReaction(() => {
    return sharedValue.value;
  }, (result, previous) => {
    if (result !== previous) {
       console.log(result)
    }
 }, []); // No need to pass dependencies

Solution with useDerivedValue

const sharedValue = useSharedValue(0);

useDerivedValue(() => {
    console.log(sharedValue.value);
}, []); // No need to pass dependencies

Millenarian answered 14/10, 2022 at 14:31 Comment(0)
P
1

If you want to trigger a function when value changes then you should use it like this

useAnimatedReaction(
() => {
  return position.value;
},
(preared, prev) => {
  runOnJS(onPositionChanged)(preared, index);
},
[]);

In this case, onPositionChanged is a callback provided by the parent component. It takes position and index as parameters. We use runOnJS to execute it because it's a native operation, and JavaScript isn't aware of it

Peach answered 25/2 at 22:29 Comment(0)
C
0

useSharedValue in the Reanimated v2 library actually returns a reference and in react useEffect does not trigger on mutation in reference variable. So if you want to execute functions with changing useSharedValue I suggest you use useCallback or a function trigger.

EDIT:

UseCallback would only work for node references such as

const Component = () => {
  const [isMounted, toggle] = useReducer((p) => !p, true);
  const [elementRect, setElementRect] = useState();

  const handleRect = useCallback((node) => {
    setElementRect(node?.getBoundingClientRect());
  }, []);

  return (
    <>
      {isMounted && <div ref={handleRect}>Example</div>}
      <button onClick={toggle}>Toggle</button>
      <pre>{JSON.stringify(elementRect, null, 2)}</pre>
    </>
  );
};

If you want to make one with sharedRef then functional trigger is your only option:

const Component = () => {

const shared = useSharedValue(0);
const _incShared = () => shared.value++;

return(
<View></View>
)
}
Chiropody answered 22/9, 2022 at 13:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.