简体   繁体   English

从异步函数获取数据到另一个函数 React JS

[英]get data from async function to another function React JS

I have problem with async function.我有异步功能的问题。 I need track.user in another function but my func getTracks() async.我需要track.user在另一个函数中,但我的 func getTracks() 异步。 I don't have clue how can i get this.我不知道我怎么能得到这个。

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);
            })
    }
}

You can move the second request to the then block of the dependent first request,ie, getTracks .您可以将第二个请求移至依赖的第一个请求的then块,即getTracks Also, you shouldn't mix then and await.另外,你不应该混合然后等待。

useEffect(() => {
    const getTracks = () => {
        httpClient.get(`/track/${id}`)
            .then((response) => {
                setTrack(response.data);
                httpClient.get(`/profile/${response.data.user}/`)
               .then((response) => {
                 setUser(response.data);
               })
            })
    }
    getTracks();
}, [])

I would declare both functions at the beginning of the component (you can later optimise them with useCallback but it's not that important in this phase).我会在组件的开头声明这两个函数(您可以稍后使用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);
  })
}

I would then call an async function inside the useEffect hook.然后我会在useEffect挂钩中调用一个async函数。 There are a couple of ways of doing it: you can either declare an async function in the useEffect hook and call it immediately, or you can call an anonymous async function.有几种方法可以做到这一点:您可以在useEffect挂钩中声明一个async函数并立即调用它,或者您可以调用一个匿名async函数。 I prefer the latter for brevity, so here it is:为了简洁起见,我更喜欢后者,所以这里是:

useEffect(() => {
  (async () => {
    await getTracks();
    getUser();
  })();
}, []);

Now when you call getUser you should be sure that getTracks has already set the track variable.现在,当您调用getUser时,您应该确保getTracks已经设置了track变量。

Here is the complete component:这是完整的组件:

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

EDIT 07/18/22编辑 07/18/22

Following Noel 's comments and linkedsandbox , I figured out that my answer wasn't working.Noel的评论和链接的沙箱之后,我发现我的答案不起作用。 The reason why it wasn't working is that the track variable was't available right after the getTrack() hook execution: it would have been available on the subsequent render.它不工作的原因是在getTrack()钩子执行后track变量不可用:它在后续渲染中是可用的。

My solution is to add a second useEffect hook that's executed every time the track variable changes.我的解决方案是添加第二个useEffect挂钩,每次track变量更改时都会执行该挂钩。 I have created two solutions with jsonplaceholder endpoints, one (see here ) which preserves the most of the original solution but adds complexity, and another one ( here ) which simplifies a lot the code by decoupling the two methods from the setTrack and setUser hooks.我创建了两个带有 jsonplaceholder 端点的解决方案,一个(参见此处)保留了大部分原始解决方案但增加了复杂性,另一个(此处)通过将这两种方法与setTracksetUser挂钩解耦来简化代码。

I'll paste here the simpler one, adapted to the OP requests.我将在此处粘贴更简单的,适合 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>
  );
}

You shouldn't be mixing then s with async/await .您不应该将then s 与async/await混合。 You should be using another useEffect that watches out for changes in the track state and then calls getUser with that new data.应该使用另一个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