Перейти к содержанию

useAnimatedReaction

Функция useAnimatedReaction позволяет реагировать на изменения в shared value. Это особенно удобно при сравнении значений, ранее хранившихся в общем значении, с текущим значением.

Справочник

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import { useAnimatedReaction } from 'react-native-reanimated';

function App() {
    useAnimatedReaction(
        () => {
            return sv.value;
        },
        (currentValue, previousValue) => {
            if (currentValue !== previousValue) {
                // do something ✨
            }
        }
    );

    // ...
}

Определения типов

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
type DependencyList = ReadonlyArray<any>;

function useAnimatedReaction<T>(
    prepare: () => T,
    react: (
        prepareResult: T,
        preparePreviousResult: T | null
    ) => void,
    dependencies?: DependencyList
): void;

Аргументы

prepare

Функция, которая должна возвращать значение, на которое вы хотите отреагировать. Значение, возвращаемое этой функцией, используется в качестве первого параметра аргумента react.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function App() {
    useAnimatedReaction(
        // highlight-start
        () => {
            return Math.floor(sv.value);
        },
        // highlight-end
        (currentValue, previousValue) => {
            // ...
        }
    );
}

react

Функция, реагирующая на изменение значения, возвращаемого функцией prepare. Функция react имеет два параметра: текущее значение из функции prepare и предыдущее значение, которое первоначально устанавливается в null.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function App() {
    useAnimatedReaction(
        () => {
            return Math.floor(sv.value);
        },
        // highlight-next-line
        (currentValue, previousValue) => {
            // ...
            // highlight-next-line
        }
    );
}

dependencies

Необязательный массив зависимостей.

Актуально только при использовании Reanimated без плагина Babel в Web.

Возвраты

useAnimatedReaction возвращает undefined.

Пример

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import React from 'react';
import {
    Button,
    StyleSheet,
    View,
    Text,
} from 'react-native';
import Animated, {
    measure,
    runOnJS,
    useAnimatedReaction,
    useAnimatedRef,
    useSharedValue,
    withSpring,
} from 'react-native-reanimated';

export default function App() {
    const animatedRef = useAnimatedRef();
    const width = useSharedValue(100);
    const [text, setText] = React.useState(width.value);

    const handlePress = () => {
        width.value = withSpring(width.value + 50);
    };

    // highlight-start
    useAnimatedReaction(
        () => width.value,
        () => {
            const measurement = measure(animatedRef);

            if (measurement !== null) {
                const measuredWidth = parseInt(
                    measurement.width,
                    10
                );
                runOnJS(setText)(measuredWidth);
            }
        }
    );
    // highlight-end

    return (
        <View style={styles.container}>
            <Animated.View
                ref={animatedRef}
                style={{ ...styles.box, width }}
            />
            <Text style={styles.label}>width: {text}</Text>
            <Button
                onPress={handlePress}
                title="Click me"
            />
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
    },
    box: {
        height: 100,
        backgroundColor: '#b58df1',
        borderRadius: 20,
    },
    label: {
        fontSize: 24,
        marginVertical: 16,
        color: '#b58df1',
    },
});

Замечания

  • Убедитесь, что в функции result не мутирует то же самое общее значение, которое было использовано в функции prepare, так как это приведет к бесконечному циклу.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    function App() {
        useAnimatedReaction(
            () => {
                // highlight-next-line
                return width.value;
            },
            (currentValue) => {
                // 🚨 An infinite loop!
                // highlight-next-line
                width.value += currentValue;
            }
        );
    }
    
  • Обратные вызовы, переданные в аргументах prepare и result, автоматически workletized и выполняются в UI thread.

  • Технически вы можете реагировать на любое значение React с состоянием, используя useAnimatedReaction, но вместо этого вам, вероятно, следует использовать useEffect.

Совместимость с платформами

Android iOS Web

Ссылки

Комментарии