如何让React JS等待异步函数执行完成后再运行,避免axios请求未完成报错
问题根因
报错的核心原因非常明确:
- 你封装的
useApplicationDatahook中,dogBreedsTest的初始值是null,axios请求是异步执行的,首次渲染时请求还没返回结果,所以拿到的dogBreedsTest就是空值 - 组件的
useState初始值只会在首次渲染时赋值一次,哪怕后续请求完成dogBreedsTest变成了有效数组,你定义的dogBreeds、breedList1两个state也不会自动同步更新;同时你首次渲染直接写useState(dogBreedsTest[0])相当于在null上取属性,本身就会触发报错。
修复步骤
1. 处理请求加载状态
两种方案二选一即可:
- 方案一:修改hook中的初始值,把
dogBreedsTest的默认值从null改成空数组,避免空值报错
// useApplicationData 内修改 const [dogBreedsTest, setDogBreeds] = useState([]);
- 方案二:在组件层面加加载拦截,请求未完成时先展示加载提示,不渲染依赖数据的内容
const { dogBreedsTest } = useApplicationData() // 加载拦截逻辑,放在所有state定义之前 if(!dogBreedsTest || dogBreedsTest.length === 0) { return <div>数据加载中...</div> } // 后续再写你的业务逻辑 const [dogBreeds, updateDogBreeds] = useState(dogBreedsTest[0]); const [breedList1, updateBreedList1] = useState(dogBreedsTest[0])
2. 同步接口返回数据到组件state
加useEffect监听dogBreedsTest的变化,请求完成拿到数据后自动更新组件的state:
useEffect(() => { if(dogBreedsTest && dogBreedsTest.length > 0) { updateDogBreeds(dogBreedsTest[0]) updateBreedList1(dogBreedsTest[0]) } }, [dogBreedsTest])
3. 修复拖拽回调逻辑
你当前的拖拽结束回调里,更新state时又重新取了dogBreedsTest[0]的初始值,会导致拖拽排序后直接被重置,要改成用你排序完成的新数组:
function handleOnDragEnd(result) { if (!result.destination) return; const items = Array.from(dogBreeds); const [reorderedItem] = items.splice(result.source.index, 1); items.splice(result.destination.index, 0, reorderedItem); for (const [index, item] of items.entries()) { item['rank'] = index + 1 } // 修改这里,用排序后的新数组更新state updateDogBreeds(items); updateBreedList1(items); }
内容的提问来源于stack exchange,提问作者Jamie Huff
相关产品推荐
相关产品推荐

