[英]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.