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

runOnUI

runOnUI позволяет асинхронно запускать workletized функции на UI thread.

Чаще всего используется либо с useEffect для запуска анимации при монтировании/демонтировании компонента, либо с функциями measure и scrollTo, которые имеют реализацию только в потоке UI.

Справочник

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { runOnUI } from 'react-native-reanimated';

function App() {
    // E.g. in event handler or in an effect
    // highlight-next-line
    runOnUI((greeting) => {
        console.log(`${greeting} from the UI thread`);
        // highlight-next-line
    })('Howdy');

    // ...
}

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

1
2
3
function runOnUI<A extends any[], R>(
    fn: (...args: A) => R
): (...args: Parameters<typeof fn>) => void;

Аргументы

fn

Ссылка на функцию, которую необходимо выполнить в потоке UI thread из потока JavaScript thread. Аргументы вашей функции должны быть переданы в функцию, возвращаемую из runOnUI, т.е. runOnUI(myWorklet)(10);.

Возвращает

runOnUI возвращает функцию, принимающую аргументы для функции, переданной в качестве первого аргумента.

Не забудьте вызвать функцию, возвращаемую из runOnUI.

Example

 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
74
75
76
77
78
79
80
81
82
import React from 'react';
import { View, StyleSheet, Text } from 'react-native';
import {
    runOnJS,
    measure,
    useAnimatedRef,
    runOnUI,
} from 'react-native-reanimated';

function MeasurableText(props) {
    const { children, onPress } = props;
    const animatedRef = useAnimatedRef();

    const handleMeasure = () => {
        // highlight-next-line
        runOnUI(() => {
            const measurements = measure(animatedRef);
            runOnJS(onPress)(measurements);
            // highlight-next-line
        })();
    };

    return (
        <Text
            style={styles.title}
            onPress={handleMeasure}
            ref={animatedRef}
        >
            {children}
        </Text>
    );
}

export default function App() {
    const [text, setText] = React.useState(0);

    const handlePress = (measurements) => {
        setText(Math.floor(measurements.width));
    };

    return (
        <View style={styles.container}>
            {['React', 'Native', 'Reanimated'].map(
                (word) => (
                    <MeasurableText
                        key={word}
                        onPress={handlePress}
                    >
                        {word}
                    </MeasurableText>
                )
            )}
            <Text style={styles.label}>width: {text}</Text>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
    },
    box: {
        height: 100,
        width: 100,
        backgroundColor: '#b58df1',
        borderRadius: 20,
        marginVertical: 64,
        alignSelf: 'center',
    },
    title: {
        fontSize: 42,
        textAlign: 'center',
        fontWeight: 'bold',
        marginRight: 8,
    },
    label: {
        fontSize: 24,
        marginVertical: 16,
        color: '#b58df1',
    },
});

Замечания

  • При реализации анимации следует сначала обратиться к более общим решениям, таким как useDerivedValue, useAnimatedReaction или выполнение кода в обратных вызовах жестов, и использовать runOnUI только после того, как вы попробовали другие методы.

  • Распространенной ошибкой является выполнение функции внутри runOnUI следующим образом: runOnUI(myWorklet(10))(). Здесь правильным будет runOnUI(myWorklet)(10).

  • Переданный в качестве аргумента обратный вызов автоматически workletized и готов к запуску на UI thread.

  • Убедитесь, что не следует выполнять runOnUI в потоке UI, так как это приведет к ошибке.

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

Android iOS Web

Ссылки

Комментарии