簡體   English   中英

從異步函數獲取數據到另一個函數 React JS

[英]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();
    })();
  }, []);
}

編輯 07/18/22

Noel的評論和鏈接的沙箱之后,我發現我的答案不起作用。 它不工作的原因是在getTrack()鈎子執行后track變量不可用:它在后續渲染中是可用的。

我的解決方案是添加第二個useEffect掛鈎,每次track變量更改時都會執行該掛鈎。 我創建了兩個帶有 jsonplaceholder 端點的解決方案,一個(參見此處)保留了大部分原始解決方案但增加了復雜性,另一個(此處)通過將這兩種方法與setTracksetUser掛鈎解耦來簡化代碼。

我將在此處粘貼更簡單的,適合 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM