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

如何将一维数组转为二维数组并存储到React Native状态中?

问题分析与解决方案

一、一维转二维的效率优化

你原来的转换代码遍历了两次数组来生成行、列两个二维数组,其实可以一次遍历完成两个结构的构建,把时间复杂度从O(2n)降到O(n),效率提升明显。

先看你原来的代码:

for (let i = 0; i < this.state.array.length; i++) { 
  let row = this.state.array[i].row; 
  if (newSeats[row] === undefined) newSeats[row] = []; 
  newSeats[row].push(this.state.array[i]); 
} 
for (let i = 0; i < this.state.array.length; i++) { 
  let column = this.state.array[i].column; 
  if (newSeatss[column] === undefined) newSeatss[column] = []; 
  newSeatss[column].push(this.state.array[i]); 
}

优化后的单次遍历版本:

const convertTo2D = (seats) => {
  const rowBased = [];
  const columnBased = [];
  seats.forEach(seat => {
    const { row, column } = seat;
    // 构建行维度的二维数组
    if (!rowBased[row]) rowBased[row] = [];
    rowBased[row].push(seat);
    // 同时构建列维度的二维数组
    if (!columnBased[column]) columnBased[column] = [];
    columnBased[column].push(seat);
  });
  return { rowBased, columnBased };
}

另外你用reduce构建行二维数组的思路是对的,但要注意:如果你的row是字符串类型(比如数据里的"0""1"),数组会自动把索引转成数字,但如果出现非连续的row值(比如"a""b"),用对象存储会更稳妥;如果row是连续数字字符串,用数组没问题。

二、解决setState"最大调用深度超限"错误

这个错误的核心原因是你在render函数里直接调用了会触发setState的方法,导致render → 调用方法 → setState → 重新render → 再次调用方法的无限循环。

看你的代码,当前seats()方法只是console.log,但如果之前你在这个方法里写了setState({ seatArray: arr2d }),就会触发无限循环。正确的做法是:

  1. 不要在render里执行修改state的逻辑,应该在数据获取完成后(比如componentDidMount的回调)完成转换并设置state。
  2. 如果后续selectedSeatLayouts会变化,用componentDidUpdate监听变化并重新转换。

修改后的componentDidMount示例:

componentDidMount() { 
  this.props.fetchSeatLayout(this.props.selectedBus.id, (data) => { 
    // 在这里完成一维转二维的转换,再存入state
    const { rowBased, columnBased } = convertTo2D(data.seats);
    this.setState({ 
      isLoading : false, 
      selectedSeatLayouts: data.seats,
      rowBasedSeats: rowBased,
      columnBasedSeats: columnBased
    }) 
  }) 
}

如果后续selectedSeatLayouts可能更新,补充componentDidUpdate:

componentDidUpdate(prevProps, prevState) {
  // 当selectedSeatLayouts变化时,重新转换并更新state
  if (prevState.selectedSeatLayouts !== this.state.selectedSeatLayouts) {
    const { rowBased, columnBased } = convertTo2D(this.state.selectedSeatLayouts);
    this.setState({ rowBasedSeats: rowBased, columnBasedSeats: columnBased });
  }
}

之后在render里直接用state里的转换后数组即可,比如用FlatList渲染行:

render() { 
  const { rowBasedSeats } = this.state;
  return( 
    <View style={styles.container}> 
      <Loader loading={this.state.isLoading} /> 
      <View style={{ flex: 1 }}> 
        <View style={styles.headerContainer}> 
          <View style={{ paddingTop: 50, paddingHorizontal: 20, alignItems: 'center' }}> 
            <Text>30 Sep, 2020</Text> 
          </View> 
        </View> 
        <View style={styles.bodyContainer}> 
          <FlatList
            data={rowBasedSeats.filter(Boolean)} {/* 过滤空行(如果row不连续) */}
            renderItem={({ item }) => (
              <View style={{ flexDirection: 'row', gap: 8, padding: 4 }}>
                {item.map(seat => (
                  <TouchableOpacity 
                    key={`${seat.row}-${seat.column}`}
                    style={{ padding: 12, backgroundColor: '#f0eff4', borderRadius: 4 }}
                  >
                    <Text>{seat.name}</Text>
                  </TouchableOpacity>
                ))}
              </View>
            )}
            keyExtractor={(item, index) => index.toString()}
          />
        </View> 
      </View> 
    </View> 
  ) 
}

三、额外优化建议

  • 把字符串类型的row/column转为数字:用parseInt(row, 10)转换,避免数组出现不必要的空槽(比如row是"2"时,数组0、1索引会是undefined)。
  • 去重处理:如果seat数据可能存在重复的row+column组合,转换前先做去重,避免二维数组出现重复项。
  • 迁移到函数组件+hooks:类组件可以逐步换成函数组件,用useState和useEffect处理状态和副作用会更简洁,示例如下:
const SeatLayout = ({ selectedBus, fetchSeatLayout }) => {
  const [isLoading, setIsLoading] = useState(true);
  const [selectedSeatLayouts, setSelectedSeatLayouts] = useState([]);
  const [rowBasedSeats, setRowBasedSeats] = useState([]);
  const [columnBasedSeats, setColumnBasedSeats] = useState([]);

  // 初始获取座位数据
  useEffect(() => {
    fetchSeatLayout(selectedBus.id, (data) => {
      setSelectedSeatLayouts(data.seats);
      const { rowBased, columnBased } = convertTo2D(data.seats);
      setRowBasedSeats(rowBased);
      setColumnBasedSeats(columnBased);
      setIsLoading(false);
    });
  }, [selectedBus.id, fetchSeatLayout]);

  // 监听座位数据变化,重新转换
  useEffect(() => {
    if (selectedSeatLayouts.length > 0) {
      const { rowBased, columnBased } = convertTo2D(selectedSeatLayouts);
      setRowBasedSeats(rowBased);
      setColumnBasedSeats(columnBased);
    }
  }, [selectedSeatLayouts]);

  // 渲染部分...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 15:27:46