Ошибка в моем собственном коде реагирования с использованием обработчика жестов

Я использую React Native Gesture Handler в js-файле, и когда я запускаю код, я получаю эту ошибку

ОШИБКА [реагировать-родной-жест-обработчик] Некоторые обратные вызовы в жесте являются рабочими программами, а некоторые нет. Либо убедитесь, что все обратные вызовы помечены как «рабочие», если вы хотите запускать их в потоке пользовательского интерфейса, либо используйте модификатор «.runOnJS(true)» в жесте явно, чтобы запускать все обратные вызовы в потоке JS.

КОД:

` импортировать * как React из 'реагировать'; импортировать {Просмотр, Текст, Размеры} из «реагировать на родной»; импортировать стили из «../styles/style_home» импортировать * как Animatable из 'реагировать-родной-анимируемый' импортируйте {Canvas, Path, Skia} из @shopify/react-native-skia; импортировать {curveBasis, line, ScaleLinear, ScalePoint} из 'd3'; импортировать DataPalmas из «../../assets/csvjson.json» импортировать градиент из './Gradient' импортировать XAxisText из './XAxisText'; импорт {зажим, runOnJS, useSharedValue, withDelay, withTiming} из 'реагировать-родной-реанимированный'; импортировать курсор из './Cursor' Импортировать { Жест, Детектор жестов, PanGestureHandlerEventPayload, } из 'реагировать-родной-жест-обработчик'; импортировать {getYForX, parse} из 'реагировать-native-redash';

export default function () {
    const [showCursor, setShowCursor] = React.useState(false)
    const animationLine = useSharedValue(0)
    const animationGradient = useSharedValue({x: 0, y: 0})
    const cx = useSharedValue(0)
    const cy = useSharedValue(0)

    React.useEffect(() => {
        animationLine.value = withTiming(1, {duration:2000})
        animationGradient.value = withDelay(2000, withTiming({x: 0, y: chartHeight}, {duration: 1000}))
    }, [])

    const chartHeight = 150
    const chartWidth = Dimensions.get('window').width
    const chartMargin = 20
    const data = DataPalmas

    const xDomain = data.map((dataPoint) => dataPoint.Data)
    const xRange = [chartMargin, chartWidth - chartMargin]
    const x = scalePoint().domain(xDomain).range(xRange).padding(0)
    const stepX = x.step()
    const max = Math.max(...data.map(val => val.Precipitacao))
    const min = Math.min(...data.map(val => val.Precipitacao))

    const yDomain = [min, max]
    const yRange = [chartHeight, 0]
    const y = scaleLinear().domain(yDomain).range(yRange)

    const curvedLine = line()
    .x(d => x(d.Data))
    .y(d => y(d.Precipitacao))
    .curve(curveBasis)(data)

    const linePath = Skia.Path.MakeFromSVGString(curvedLine)
    const path = parse(linePath.toSVGString())

    function handleGestureEvent(e){
        const clampValue = clamp(
            Math.floor(e.absoluteX / stepX) * stepX + chartMargin,
            chartMargin,
            chartWidth - chartMargin,
        )
        cx.value = clampValue
        cy.value = getYForX(path, Math.floor(clampValue))
    }
    const pan = Gesture.Pan()
        .onTouchesDown(() => {
            setShowCursor(true)
        })
        .onTouchesUp(() => {
            setShowCursor(false)
        })
        .onBegin(handleGestureEvent)
        .onChange(handleGestureEvent)

    return (
    <Animatable.View style = {styles.container__graphic} animation = {"fadeInLeft"}>
        <GestureDetector gesture = {pan}>
            <Canvas
            style = {{
                width: chartWidth, 
                height: chartHeight+30,
            }}>
                <Path 
                path = {linePath} 
                style = {'stroke'} 
                strokeWidth = {2} 
                color = {'#0bb861'} 
                strokeCap = {'round'}
                start = {0}
                end = {animationLine}/>
                <Gradient
                    chartHeight = {chartHeight}
                    chartMargin = {chartMargin}
                    chartWidth = {chartWidth}
                    curvedLine = {curvedLine}
                    animationGradient = {animationGradient}
                />
                {data.map((dataPoint, index) => (
                    <XAxisText
                        x = {x(dataPoint.Data)}
                        y = {chartHeight}
                        text = {dataPoint.Data}
                        key = {index}
                    />
                ))}
                {showCursor && 
                <Cursor 
                    cx = {cx}
                    cy = {cy}
                    chartHeight = {chartHeight}
                />}
                
            </Canvas>
        </GestureDetector>
    </Animatable.View>
    );
}`

Когда я использую «worklet» в этой функции, приложение вылетает, когда я нажимаю

function handleGestureEvent(e){
    **'worklet'**
    const clampValue = clamp(
        Math.floor(e.absoluteX / stepX) * stepX + chartMargin,
        chartMargin,
        chartWidth - chartMargin,
    )
    cx.value = clampValue
    cy.value = getYForX(path, Math.floor(clampValue))
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
216
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно добавить .runOnJS(true) к вашему Gesture.Pan() вызову, например:

    const pan = Gesture.Pan()
        .runOnJS(true)
        .onTouchesDown(() => {
            setShowCursor(true)
        })
        .onTouchesUp(() => {
            setShowCursor(false)
        })
        .onBegin(handleGestureEvent)
        .onChange(handleGestureEvent)

Плагин Babel от Reanimated автоматически обрабатывает обратные вызовы, когда обратные вызовы объединены в цепочку. Использование .runOnJS(true) заставит каждый обратный вызов в цепочке выполняться в потоке js, что может отрицательно повлиять на производительность, если в цепочке есть обратный вызов с логикой анимации внутри, поэтому было бы более оптимально использовать функцию runOnJS выборочно для функций, которые должны выполняться на JS. поток (например, установщики состояния).

Сбой при работе вручную handleGestureEvent — это еще одна проблема, которая может быть внутренней ошибкой react-native-reanimated (например, вот эта). Я бы попробовал обновить react-native-reanimated до последней версии или переместить код handleGestureEvent в обратные вызовы .onBegin и .onChange напрямую, используя автоматическую ворлетизацию, и пометить дублирующуюся логику с помощью FIXME (или, что еще лучше, создать заявку на технический долг) провести рефакторинг позже, когда ошибка будет обнаружена и исправлена.

const pan = Gesture.Pan()
  .onTouchesDown(runOnJS(() => {
      setShowCursor(true)
  }))
  .onTouchesUp(runOnJS(() => {
      setShowCursor(false)
  }))
  .onBegin((e) => {
    const clampValue = clamp(
        Math.floor(e.absoluteX / stepX) * stepX + chartMargin,
        chartMargin,
        chartWidth - chartMargin,
    )
    cx.value = clampValue
    cy.value = getYForX(path, Math.floor(clampValue))
  })
  .onChange((e) => {
    const clampValue = clamp(
        Math.floor(e.absoluteX / stepX) * stepX + chartMargin,
        chartMargin,
        chartWidth - chartMargin,
    )
    cx.value = clampValue
    cy.value = getYForX(path, Math.floor(clampValue))
  })

Другие вопросы по теме