UNPKG

2.23 kBPlain TextView Raw
1'use strict';
2import { useEffect, useRef } from 'react';
3import { initialUpdaterRun } from '../animation';
4import type { SharedValue, WorkletFunction } from '../commonTypes';
5import { makeMutable, startMapper, stopMapper } from '../core';
6import type { DependencyList } from './commonTypes';
7import { shouldBeUseWeb } from '../PlatformChecker';
8
9export type DerivedValue<Value> = Readonly<SharedValue<Value>>;
10
11/**
12 * Lets you create new shared values based on existing ones while keeping them reactive.
13 *
14 * @param updater - A function called whenever at least one of the shared values or state used in the function body changes.
15 * @param dependencies - An optional array of dependencies. Only relevant when using Reanimated without the Babel plugin on the Web.
16 * @returns A new readonly shared value based on a value returned from the updater function
17 * @see https://docs.swmansion.com/react-native-reanimated/docs/core/useDerivedValue
18 */
19// @ts-expect-error This overload is required by our API.
20export function useDerivedValue<Value>(
21 updater: () => Value,
22 dependencies?: DependencyList
23): DerivedValue<Value>;
24
25export function useDerivedValue<Value>(
26 updater: WorkletFunction<[], Value>,
27 dependencies?: DependencyList
28): DerivedValue<Value> {
29 const initRef = useRef<SharedValue<Value> | null>(null);
30 let inputs = Object.values(updater.__closure ?? {});
31 if (shouldBeUseWeb()) {
32 if (!inputs.length && dependencies?.length) {
33 // let web work without a Babel/SWC plugin
34 inputs = dependencies;
35 }
36 }
37
38 // build dependencies
39 if (dependencies === undefined) {
40 dependencies = [...inputs, updater.__workletHash];
41 } else {
42 dependencies.push(updater.__workletHash);
43 }
44
45 if (initRef.current === null) {
46 initRef.current = makeMutable(initialUpdaterRun(updater));
47 }
48
49 const sharedValue: SharedValue<Value> = initRef.current;
50
51 useEffect(() => {
52 const fun = () => {
53 'worklet';
54 sharedValue.value = updater();
55 };
56 const mapperId = startMapper(fun, inputs, [sharedValue]);
57 return () => {
58 stopMapper(mapperId);
59 };
60 }, dependencies);
61
62 useEffect(() => {
63 return () => {
64 initRef.current = null;
65 };
66 }, []);
67
68 return sharedValue;
69}