You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native:如何将全局状态传入useAnimatedGestureHandler的OnStart钩子

React Native 可拖拽Tile组件层级控制问题

需求:实现多个可拖拽Tile,每次拖拽或点击时,将全局最高z轴值加1并赋值给当前操作的Tile,使其始终处于层级最上层。当前在父组件通过useState维护maxZ状态,但无法在子组件的useAnimatedGestureHandler的onStart钩子中正确更新并同步该值——useState运行在JS线程,而手势钩子运行在UI线程,尝试useSharedValue、runOnJS等跨线程通信方法未成功。

解决方案

核心思路

将全局层级状态改用useSharedValue维护(支持跨线程访问),配合runOnJS实现UI线程到JS线程的状态更新,同时通过useDerivedValue确保子组件能实时获取最新的全局层级值。

修改步骤

  1. 父组件替换useState为useSharedValue来维护maxZ,并定义全局更新方法
  2. 将maxZ共享值和更新方法传递给子组件
  3. 子组件在手势onStart钩子中,先调用全局更新方法让maxZ自增,再将最新的maxZ赋值给当前Tile的currentZ
  4. 用useDerivedValue监听maxZ变化,确保子组件能实时同步全局层级状态

修改后的完整代码

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  useAnimatedGestureHandler,
  useDerivedValue,
  runOnJS
} from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';

const tileWidth = 100;
const tileHeight = 60;

export default function App() {
  // 用useSharedValue替代useState,支持跨线程访问
  const maxZ = useSharedValue(0);

  // 全局更新maxZ的方法,运行在JS线程
  const updateMaxZ = () => {
    maxZ.value += 1;
  };

  const DraggableTile = ({ txt }) => {
    const translateX = useSharedValue(0);
    const translateY = useSharedValue(0);
    const currentZ = useSharedValue(0);

    // 监听全局maxZ变化,确保当前组件能获取最新值
    useDerivedValue(() => {
      currentZ.value = maxZ.value;
    });

    const panGestureEvent = useAnimatedGestureHandler({
      onStart: (event, context) => {
        // 在UI线程中调用JS线程的更新方法
        runOnJS(updateMaxZ)();
        context.x = translateX.value;
        context.y = translateY.value;
      },
      onActive: (event, context) => {
        translateX.value = event.translationX + context.x;
        translateY.value = event.translationY + context.y;
      },
      onEnd: () => {}
    });

    const repositionedStyle = useAnimatedStyle(() => {
      return {
        transform: [{ translateX: translateX.value }, { translateY: translateY.value }],
        zIndex: currentZ.value
      };
    });

    return (
      <PanGestureHandler onGestureEvent={panGestureEvent}>
        <Animated.View style={[styles.tile, repositionedStyle]}>
          <Text style={styles.tileText}>{txt}</Text>
        </Animated.View>
      </PanGestureHandler>
    );
  };

  return (
    <View style={styles.container}>
      <DraggableTile txt="101" />
      <DraggableTile txt="102" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#ddd',
    alignItems: 'center',
    justifyContent: 'center',
  },
  tile: {
    width: tileWidth,
    height: tileHeight,
    backgroundColor: "#fff",
    borderWidth: 1,
    borderColor: "#aaa",
    display:"inline-flex",
    flexDirection:"row",
    alignItems:"center",
    justifyContent:"center"
  },
  tileText: {
    fontSize:28,
    fontWeight:600
  }
});

内容的提问来源于stack exchange,提问作者Jonathan Atkinson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:53:13