React中为何第二个函数不等待首个异步函数执行完毕?如何实现等待?
问题原因
fetchItems是异步函数,调用它时不会阻塞后续代码执行——它会立刻返回一个Promise,doSomethingWithItems会直接启动运行,完全等不及请求完成。- 就算
fetchItems里的请求成功返回,setItems是异步更新React状态的方法,调用后items不会立刻变成新值,此时doSomethingWithItems里用到的还是初始的undefined,甚至会因为对undefined调用filter抛出错误。
解决方案
方案一:在请求完成后直接处理(最简洁)
既然要等请求返回后再过滤,直接在fetchItems里完成过滤逻辑即可,无需单独调用函数:
const [items, setItems] = useState(); const fetchItems = async () => { try { let responseData = await sendRequest(`${process.env.REACT_APP_BACKEND_URL}/items/user/${userId}`); // 直接对请求返回的数据过滤后再设置状态 const filteredItems = responseData.items.filter(x => x.title === 'something'); setItems(filteredItems); } catch (err) {} }; useEffect(() => { fetchItems(); }, []);
方案二:用useEffect监听items状态变化
如果doSomethingWithItems需要复用或逻辑复杂,可以通过监听items的变化,在数据就绪时自动执行过滤:
const [items, setItems] = useState(); const fetchItems = async () => { try { let responseData = await sendRequest(`${process.env.REACT_APP_BACKEND_URL}/items/user/${userId}`); setItems(responseData.items); } catch (err) {} }; const doSomethingWithItems = () => { if (!items) return; // 增加判断,避免未初始化时调用filter报错 const filteredItems = items.filter(x => x.title === 'something'); setItems(filteredItems); }; // 监听items,当数据存在时执行过滤 useEffect(() => { if (items) { doSomethingWithItems(); } }, [items]); useEffect(() => { fetchItems(); }, []);
方案三:修改函数参数,直接传递请求数据
如果一定要保留doSomethingWithItems的独立调用,可以让它接收数据参数,避免依赖异步更新的state:
const [items, setItems] = useState(); const fetchItems = async () => { try { let responseData = await sendRequest(`${process.env.REACT_APP_BACKEND_URL}/items/user/${userId}`); // 直接把请求返回的数据传给处理函数 doSomethingWithItems(responseData.items); } catch (err) {} }; // 函数接收外部传入的数据,不再依赖组件state const doSomethingWithItems = (itemsData) => { const filteredItems = itemsData.filter(x => x.title === 'something'); setItems(filteredItems); }; useEffect(() => { fetchItems(); }, []);
内容的提问来源于stack exchange,提问作者dawphin777
相关产品推荐
相关产品推荐

