[英]get data from async function to another function React JS
我有异步功能的问题。 我需要track.user
在另一个函数中,但我的 func getTracks() 异步。 我不知道我怎么能得到这个。
const Player = ({trackUrl, index, cover, id}) => {
const [track, setTrack] = useState({})
const [user, setUser] = useState({})
useEffect(() => {
const getTracks = async () => {
await httpClient.get(`/track/${id}`)
.then((response) => {
setTrack(response.data);
})
}
getTracks();
getUser() // track.user undefined
}, [])
const getUser = async() => {
await httpClient.get(`/profile/${track.user}/`)
.then((response) => {
setUser(response.data);
})
}
}
您可以将第二个请求移至依赖的第一个请求的then
块,即getTracks
。 另外,你不应该混合然后等待。
useEffect(() => {
const getTracks = () => {
httpClient.get(`/track/${id}`)
.then((response) => {
setTrack(response.data);
httpClient.get(`/profile/${response.data.user}/`)
.then((response) => {
setUser(response.data);
})
})
}
getTracks();
}, [])
我会在组件的开头声明这两个函数(您可以稍后使用useCallback
优化它们,但在这个阶段并不那么重要)。
const getTracks = async () => {
await httpClient.get(`/track/${id}`)
.then((response) => {
setTrack(response.data);
})
}
const getUser = async() => {
await httpClient.get(`/profile/${track.user}/`)
.then((response) => {
setUser(response.data);
})
}
然后我会在useEffect
挂钩中调用一个async
函数。 有几种方法可以做到这一点:您可以在useEffect
挂钩中声明一个async
函数并立即调用它,或者您可以调用一个匿名async
函数。 为了简洁起见,我更喜欢后者,所以这里是:
useEffect(() => {
(async () => {
await getTracks();
getUser();
})();
}, []);
现在,当您调用getUser
时,您应该确保getTracks
已经设置了track
变量。
这是完整的组件:
const Player = ({trackUrl, index, cover, id}) => {
const [track, setTrack] = useState({})
const [user, setUser] = useState({})
const getTracks = async () => {
await httpClient.get(`/track/${id}`)
.then((response) => {
setTrack(response.data);
})
}
const getUser = async() => {
await httpClient.get(`/profile/${track.user}/`)
.then((response) => {
setUser(response.data);
})
}
useEffect(() => {
(async () => {
await getTracks();
getUser();
})();
}, []);
}
在Noel的评论和链接的沙箱之后,我发现我的答案不起作用。 它不工作的原因是在getTrack()
钩子执行后track
变量不可用:它在后续渲染中是可用的。
我的解决方案是添加第二个useEffect
挂钩,每次track
变量更改时都会执行该挂钩。 我创建了两个带有 jsonplaceholder 端点的解决方案,一个(参见此处)保留了大部分原始解决方案但增加了复杂性,另一个(此处)通过将这两种方法与setTrack
和setUser
挂钩解耦来简化代码。
我将在此处粘贴更简单的,适合 OP 请求。
export default function Player({ trackUrl, index, cover, id }) {
const [track, setTrack] = useState({});
const [user, setUser] = useState({});
const getTracks = async () => {
// only return the value of the call
return await httpClient.get(`/track/${id}`);
};
const getUser = async (track) => {
// take track as a parameter and call the endpoint
console.log(track, track.id, 'test');
return await httpClient.get(`profile/${track.user}`);
};
useEffect(() => {
(async () => {
const trackResult = await getTracks();
// we call setTrack outside of `getTracks`
setTrack(trackResult);
})();
}, []);
useEffect(() => {
(async () => {
if (track && Object.entries(track).length > 0) {
// we only call `getUser` if we are sure that track has at least one entry
const userResult = await getUser(track);
console.log(userResult);
setUser(userResult);
}
})();
}, [track]);
return (
<div className="App">{user && user.id ? user.id : "Not computed"}</div>
);
}
您不应该将then
s 与async/await
混合。 您应该使用另一个useEffect
来监视track
状态的变化,然后使用该新数据调用getUser
。
function Player(props) { const { trackUrl, index, cover, id } = props; const [ track, setTrack ] = useState({}); const [ user, setUser ] = useState({}); async function getTracks(endpoint) { const response = await httpClient.get(endpoint); const data = await response.json(); setTrack(data); } async function getUser(endpoint) { const response = await httpClient.get(endpoint); const data = await response.json(); setUser(data); } useEffect(() => { if (id) getTracks(`/track/${id}`); }, []); useEffect(() => { if (track.user) getUser(`/profile/${track.user}`); }, [track]); }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.