React Native调用setState更新分类列表时应用冻结问题排查求助
问题根因
你的应用冻结是loadViews方法中存在死循环导致的:
- 非平板设备场景下,
isTablet为false的else分支,仅执行了viewRows.push(this.renderEvenRow(i, categories[i])),没有给循环变量i做自增操作,i永远保持初始值0,只要categories数组长度大于0就会无限循环,卡死JS线程。 - 平板设备的odd行分支也存在遗漏:当
i == categories.length - 1(只剩最后一个分类)的判断分支中,同样没有执行i += 1,也会触发死循环。
你注释setState时,state中categories是空数组,循环不会执行,所以不会触发卡死问题,控制台也能正常打印接口返回的内容。
修复方案
修改loadViews方法的两处逻辑即可:
loadViews() { let i = 0; let rowType = "odd"; let viewRows = []; const { categories } = this.state; console.log(categories.length); while (i < categories.length) { console.log("//", i); if (isTablet) { switch (rowType) { case "odd": if (i == categories.length - 1) { viewRows.push(this.renderEvenRow(i, categories[i])); // 新增:最后一项处理完后i自增 i += 1; } else { viewRows.push( this.renderOddRow(i, categories[i], categories[i + 1]) ); rowType = "even"; i += 2; } break; case "even": viewRows.push(this.renderEvenRow(i, categories[i])); rowType = "odd"; i += 1; break; default: break; } } else { viewRows.push(this.renderEvenRow(i, categories[i])); // 新增:非平板场景每处理一项i自增 i += 1; } } return viewRows; }
额外优化建议
- 可以将S3图片地址的获取逻辑做并发处理,减少接口等待时间:把for..of的串行请求改成
Promise.all并行请求所有图片地址。 - 建议替换为React Native官方的
FlatList组件实现列表渲染,替代手动拼接渲染数组,性能更好也更不容易出现循环逻辑错误。
内容的提问来源于stack exchange,提问作者Malcolm S
相关产品推荐
相关产品推荐

