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

React Native单词搜索游戏:拖拽选字母与矩阵状态存储问题求助

问题解决方案

一、矩阵信息存入State失败的解决方法

React Native处理二维数组这类复杂引用类型时,直接赋值会导致State无法正确感知变化,需通过不可变更新和深拷贝处理:

  1. 初始化State并加载数据
    用useState初始化空数组,在组件挂载或数据就绪时,对原始矩阵数据深拷贝后存入State:
import { useState, useEffect } from 'react';

const [gridData, setGridData] = useState([]);

useEffect(() => {
  // 深拷贝避免引用共享,确保State能检测到变化
  const copiedGrid = JSON.parse(JSON.stringify(result.structure.content));
  setGridData(copiedGrid);
}, [result.structure.content]);
  1. 修改State中的单元格状态
    更新单元格(比如选中状态)时,必须用不可变方式修改,禁止直接操作State原对象:
const updateCellSelection = (cellId) => {
  setGridData(prevGrid => {
    return prevGrid.map(row => 
      row.map(cell => 
        cell.id === cellId ? {...cell, selected: !cell.selected} : cell
      )
    );
  });
};

二、手势拖动无法触发事件的解决方法

给每个单元格单独绑定PanGestureHandler会导致拖动时手势无法在单元格间传递,正确做法是在整个矩阵外层添加单个手势处理器,跟踪触摸位置并判断选中的单元格:

1. 重构手势处理逻辑

用react-native-reanimated的useAnimatedGestureHandler处理手势的开始、移动、结束事件:

import { PanGestureHandler } from 'react-native-gesture-handler';
import { useAnimatedGestureHandler, useSharedValue } from 'react-native-reanimated';
import { useRef } from 'react';

const YourComponent = () => {
  const [gridData, setGridData] = useState([]);
  const panX = useSharedValue(0);
  const panY = useSharedValue(0);
  // 引用矩阵容器,用于获取布局坐标
  const containerRef = useRef(null);

  // 手势处理器
  const gestureHandler = useAnimatedGestureHandler({
    onStart: (event) => {
      // 手势开始时,判断初始触摸位置的单元格
      handleCellSelection(event.x, event.y);
    },
    onActive: (event) => {
      panX.value += event.translationX;
      panY.value += event.translationY;
      // 手势移动时,实时更新选中的单元格
      handleCellSelection(event.x, event.y);
    },
    onEnd: () => {
      // 手势结束后,可添加单词校验逻辑
      // validateSelectedWords();
    },
  });

  // 根据触摸坐标计算选中的单元格
  const handleCellSelection = (x, y) => {
    const containerLayout = containerRef.current?.layout;
    if (!containerLayout || !gridData.length) return;

    const columnWidth = S.gridColumnWidth(gridData[0].length);
    // 计算相对于矩阵容器的坐标
    const relativeX = x - containerLayout.x;
    const relativeY = y - containerLayout.y;

    // 计算对应的行和列索引
    const rowIndex = Math.floor(relativeY / columnWidth);
    const colIndex = Math.floor(relativeX / columnWidth);

    // 边界校验
    if (rowIndex >= 0 && rowIndex < gridData.length && colIndex >= 0 && colIndex < gridData[rowIndex].length) {
      const targetCell = gridData[rowIndex][colIndex];
      updateCellSelection(targetCell.id); // 调用之前的状态更新函数
    }
  };

  // 省略State初始化和updateCellSelection函数...

  return (
    <GestureHandlerRootView>
      <PanGestureHandler onGestureEvent={gestureHandler}>
        <Animated.View
          ref={containerRef}
          onLayout={(e) => containerRef.current = { layout: e.nativeEvent.layout }}
          style={{ paddingTop: 18 }}
        >
          {gridData.map((grid, index) => (
            <S.Line key={index}>
              {grid.map(row => {
                const columnWidth = S.gridColumnWidth(grid.length);
                return (
                  <Animated.View
                    key={row.id}
                    style={[
                      ...styleGridSelect(row),
                      { width: columnWidth, height: columnWidth }
                    ]}
                  >
                    <Animated.Text
                      style={[
                        S.gridStyles.text,
                        {
                          textAlign: 'center',
                          fontSize: columnWidth / Platform.select({ ios: 1.3, android: 1.5 })
                        }
                      ]}
                    >
                      {row.letter}
                    </Animated.Text>
                  </Animated.View>
                );
              })}
            </S.Line>
          ))}
        </Animated.View>
      </PanGestureHandler>
    </GestureHandlerRootView>
  );
};

2. 关键说明

  • 移除每个单元格的PanGestureHandler,改用外层统一处理,确保拖动时能持续跟踪触摸位置。
  • 通过onLayout获取矩阵容器的坐标,计算触摸点对应的单元格索引。
  • 使用useSharedValue存储手势位置,配合reanimated实现流畅的手势跟踪。

内容的提问来源于stack exchange,提问作者Bruno Souza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 00:05:15