React冒泡排序可视化时DOM高度未随排序过程动态更新问题
问题核心原因
- JS是单线程运行,你写的同步
while+for排序循环会直接占满主线程,期间浏览器没有空闲执行DOM重绘,所有DOM修改都会被攒到整个循环跑完才一次性执行,自然看不到中间过程。 - 你直接修改state引用的原数组(
arraY[i] = smaller)属于直接变更状态,React检测不到状态变化,不会触发重渲染;就算你在循环里连续调用setArray,同步执行的setState会被React批量合并,最终只会渲染最后一次的结果。 - 之前试
setTimeout没效果,本质是没有把每一步排序操作拆成异步任务按间隔依次执行,要么是给整个排序套了一层延迟,要么是循环里setTimeout的延迟时间没有按步长递增,所有回调几乎同时触发,还是看不到逐帧变化。
修复方案
- 删掉手动操作ref改DOM的逻辑,React下视图完全由state驱动,数组每变一次就
setArray传新的数组拷贝,让React自动重渲染柱状条高度,手动改DOM很容易和虚拟DOM更新冲突。 - 把同步阻塞的排序逻辑改成异步执行,每完成一次元素交换,就等待一小段时间(比如10ms)再执行下一轮比较,给浏览器留出重绘DOM的空闲时间。
- 排序开始前先拷贝一份原数组做排序操作,不要直接改state里存的原数组引用,避免状态变更检测失效。
修正后可运行代码
import { useState, useEffect } from 'react'; import './App.css'; function App() { const [array, setArray] = useState([]); // 封装延迟函数,控制动画间隔 const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // 初始化随机数组 useEffect(()=> { const startArray = []; for(let i=0; i < 51; i++){ // 直接+1避免生成0值,省掉额外判断 let randomNumber = Math.floor(Math.random() * 27) + 1; startArray.push(randomNumber) } setArray(startArray) }, []) // 异步冒泡排序 const bubbleSort = async (arr) => { // 拷贝原数组,不直接修改state引用 const sortArr = [...arr]; const len = sortArr.length; for (let i = 0; i < len - 1; i++) { for (let j = 0; j < len - 1 - i; j++) { if (sortArr[j] > sortArr[j+1]) { // 交换相邻元素 [sortArr[j], sortArr[j+1]] = [sortArr[j+1], sortArr[j]]; // 传入新数组拷贝触发重渲染 setArray([...sortArr]); // 让出主线程,等待浏览器重绘 await sleep(10); } } } } const handleSort = ()=> { bubbleSort(array); } return ( <div className="App"> <nav> <h1 onClick={handleSort}>BUBBLE SORT</h1> <h1 onClick={handleSort}>--- SORT</h1> <h1 onClick={handleSort}>--- SORT</h1> <h1 onClick={handleSort}>--- SORT</h1> </nav> <div className='container'> {array.map((item, idx)=>{ // 直接由state驱动样式,无需手动操作DOM return <div key={idx} style={{height: `${item*2}vh`}} className="bar"></div> }) } </div> </div> ); } export default App;
补充说明
- 渲染柱状条的时候记得加
key属性,数组固定长度的场景用索引当key就可以,避免React节点复用出错。 - 调整
sleep函数的入参毫秒值就能改动画速度,数值越小排序动画越快。 - 其他排序算法的可视化逻辑完全通用:每一步数组变动都生成新拷贝更新state,加短延迟让出主线程给浏览器重绘即可。
内容的提问来源于stack exchange,提问作者Coder apprentice
相关产品推荐
相关产品推荐

