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

React+TypeScript中merge函数报TypeError: left is undefined的解决咨询

修复归并排序中TypeError: left is undefined及类型错误问题

问题描述

在React+TypeScript项目中实现归并排序时,触发merge函数会报错TypeError: left is undefined。为了避免left.shift()和right.shift()的语法错误,暂时将这两个参数设为any类型,需要修复这些问题让函数正常运行。

问题根源

  1. mergeSort返回值异常:原代码用for循环套setTimeout执行递归逻辑,但setTimeout是异步的,mergeSort函数没有返回有效数组,导致传给merge的left和right都是undefined。
  2. 数组操作错误:使用splice修改原数组,不仅破坏React state的不可变性,还会导致递归过程中数组被意外修改。
  3. 类型不匹配:因为mergeSort返回undefined,把merge参数设为number[]时会出现类型错误,本质是逻辑错误导致的类型问题。

修复方案

以下是修正后的完整代码,关键改动标注如下:

import { useEffect, useContext } from "react";
import { arrContext } from "../arr-context-provider";
import Visualizer from "../visualizer";

const MergeSort: React.FC = () => {
    const [arr, setArr] = useContext<[number[], React.Dispatch<React.SetStateAction<number[]>>]>(arrContext);

    // 封装延迟函数,用于可视化步骤的间隔
    const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

    useEffect(() => {
        // 初始数组为空时不执行
        if (arr.length === 0) return;
        // 拷贝初始数组,避免修改原state
        const initialArr = [...arr];
        mergeSort(initialArr);
    }, [arr]);

    const mergeSort = async (currentArr: number[]): Promise<number[]> => {
        // 递归终止条件:数组长度小于2直接返回
        if (currentArr.length < 2) {
            return currentArr;
        }

        const mid = Math.floor(currentArr.length / 2);
        // 用slice拆分数组,不修改原数组
        const left = currentArr.slice(0, mid);
        const right = currentArr.slice(mid);

        // 递归排序左右子数组
        const sortedLeft = await mergeSort(left);
        const sortedRight = await mergeSort(right);

        // 合并后更新state,并添加延迟
        const mergedArr = await merge(sortedLeft, sortedRight);
        await delay(100);
        return mergedArr;
    };

    const merge = (left: number[], right: number[]): Promise<number[]> => {
        return new Promise(resolve => {
            const merged: number[] = [];
            // 拷贝数组避免修改原排序后的数组
            const leftCopy = [...left];
            const rightCopy = [...right];

            while (leftCopy.length && rightCopy.length) {
                if (leftCopy[0] < rightCopy[0]) {
                    merged.push(leftCopy.shift()!);
                } else {
                    merged.push(rightCopy.shift()!);
                }
            }

            const finalMerged = [...merged, ...leftCopy, ...rightCopy];
            // 更新state为合并后的数组
            setArr(finalMerged);
            resolve(finalMerged);
        });
    };

    return <Visualizer />;
};

export default MergeSort;

关键改动说明

  • 异步递归处理:把mergeSort改成异步函数,用await处理递归和延迟,确保每次排序步骤完成后再执行合并,同时保证函数返回正确的number[]。
  • 数组不可变性:用slice拆分数组,拷贝数组进行操作,避免修改原数组和React state,符合React的状态管理规范。
  • 类型修正:merge的参数明确设为number[],因为mergeSort现在返回有效的数组,类型匹配后shift()的语法错误也会消失(用!断言shift()不会返回undefined,因为已经判断了数组长度大于0)。
  • useEffect优化:添加arr作为依赖,确保数组变化时重新执行排序,同时拷贝初始数组避免直接操作state。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 02:57:42