递归async/await导致React应用崩溃问题求助
搞定你的React排序应用问题!
嘿,我帮你找到问题根源啦!你的归并排序崩溃+React渲染报错,其实是两个核心问题在搞鬼,咱们一步步拆解解决:
1. 递归调用async函数没加await,导致参数全是Promise
你的mergeSort是async函数,递归调用this.mergeSort(left)和this.mergeSort(right)的时候,返回的都是Promise对象,但你直接把这俩Promise传给了merge函数——可merge要的是实实在在的数组啊!这不仅会让merge里的left.length这类操作直接出错,还会让整个mergeSort的返回值变成嵌套的Promise,最后搞砸整个流程。
把mergeSort改成这样就好:
async mergeSort(arr) { if(arr.length < 2) { return arr; } const m = Math.floor(arr.length / 2); let left = arr.slice(0, m); let right = arr.slice(m); await this.sleep(); // 递归调用必须加await,拿到真正排序后的数组 left = await this.mergeSort(left); right = await this.mergeSort(right); // merge也是async函数,同样要await它的结果 return await this.merge(left, right); }
2. 把Promise直接塞给了React State,导致渲染报错
那个Objects are not valid as a React child的错误,说明你肯定在某个地方(比如触发排序的onSortBtn函数里)把mergeSort返回的Promise直接赋值给了state.hatArray。React可没法渲染Promise对象,这不报错才怪!
两种解决思路:
思路一:等排序完成再更新UI(适合只看最终结果的场景)
如果不需要实时看每一步排序动画,就等整个排序完成后再把结果赋值给state:
async onSortBtn() { this.setState({ sorting: true }); // 先复制当前数组,避免直接修改原state const sortedArray = await this.mergeSort([...this.state.hatArray]); // 排序完成后更新state this.setState({ hatArray: sortedArray, sorting: false, sorted: true, endTime: Date.now() }); }
思路二:实时更新每一步排序状态(要做动画就得这么搞)
如果想让用户看到每一步排序的过程,就得在merge函数里每操作一次就更新state,而不是等最后返回数组。修改后的merge函数如下:
async merge(left, right) { let result = []; // 封装一个更新state的函数,用函数式更新避免异步问题 const updateHatArray = (newArr) => { this.setState(prevState => ({ hatArray: [...newArr] })); }; while(left.length && right.length) { if(left[0].props.number <= right[0].props.number) { result.push(left.shift()); } else { result.push(right.shift()); } // 更新当前的数组状态 updateHatArray(result.concat(left, right)); await this.sleep(); } while(left.length) { result.push(left.shift()); updateHatArray(result.concat(left, right)); await this.sleep(); } while(right.length) { result.push(right.shift()); updateHatArray(result.concat(left, right)); await this.sleep(); } return result; }
这样每一步merge操作后,UI都会实时更新,用户就能看到排序的动画效果啦!
最后提个小提醒
排序开始的时候,记得把sorting设为true,禁用排序按钮,别让用户重复触发排序,不然会打乱整个流程哦~
内容的提问来源于stack exchange,提问作者shawn
相关产品推荐
相关产品推荐

