简体   繁体   English

使用 React Hooks 获取多个数据 axios

[英]Multiple fetch data axios with React Hooks

I would like to get global information from Github user and his repos(and get pinned repos will be awesome).我想从 Github 用户和他的存储库中获取全局信息(并且固定存储库会很棒)。 I try to make it with async await but It's is correct?我尝试使用 async await 来实现,但这是正确的吗? I've got 4 times reRender (4 times console log).我有 4 次 reRender(4 次控制台日志)。 It is possible to wait all component to reRender when all data is fetched?获取所有数据后是否可以等待所有组件重新渲染?

function App() {
  const [data, setData] = useState(null);
  const [repos, setRepos] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const respGlobal = await axios(`https://api.github.com/users/${username}`);
      const respRepos = await axios(`https://api.github.com/users/${username}/repos`);

      setData(respGlobal.data);
      setRepos(respRepos.data);
    };

    fetchData()

  }, []);

  if (data) {
    console.log(data, repos);
  }

  return (<h1>Hello</h1>)
}

Multiple state updates are batched but but only if it occurs from within event handlers synchronously and not setTimeouts or async-await wrapped methods .多个状态更新是批处理的,但前提是它在事件处理程序中同步发生,而不是setTimeoutsasync-await wrapped methods

This behavior is similar to classes and since in your case its performing two state update cycles due to two state update calls happening此行为类似于类,因为在您的情况下,由于发生两次状态更新调用,它会执行两个状态更新周期

So Initially you have an initial render and then you have two state updates which is why component renders three times.所以最初你有一个初始渲染,然后你有两个状态更新,这就是组件渲染三次的原因。

Since the two states in your case are related, you can create an object and update them together like this:由于您案例中的两个状态是相关的,您可以创建一个对象并将它们一起更新,如下所示:

function App() {
  const [resp, setGitData] = useState({ data: null, repos: null });

  useEffect(() => {
    const fetchData = async () => {
      const respGlobal = await axios(
        `https://api.github.com/users/${username}`
      );
      const respRepos = await axios(
        `https://api.github.com/users/${username}/repos`
      );

      setGitData({ data: respGlobal.data, repos: respGlobal.data });
    };

    fetchData();
  }, []);

  console.log('render');
  if (resp.data) {
    console.log("d", resp.data, resp.repos);
  }

  return <h1>Hello</h1>;
}

Working demo工作演示

For other researchers ( Live demo ):对于其他研究人员( 现场演示):

import React, { useEffect, useState } from "react";
import { CPromise, CanceledError } from "c-promise2";
import cpAxios from "cp-axios";

function MyComponent(props) {
  const [error, setError] = useState("");
  const [data, setData] = useState(null);
  const [repos, setRepos] = useState(null);

  useEffect(() => {
    console.log("mount");
    const promise = CPromise.from(function* () {
      try {
        console.log("fetch");
        const [respGlobal, respRepos] = [
          yield cpAxios(`https://api.github.com/users/${props.username}`),
          yield cpAxios(`https://api.github.com/users/${props.username}/repos`)
        ];

        setData(respGlobal.data);
        setRepos(respRepos.data);
      } catch (err) {
        console.warn(err);
        CanceledError.rethrow(err); //passthrough
        // handle other errors than CanceledError
        setError(err + "");
      }
    }, []);

    return () => {
      console.log("unmount");
      promise.cancel();
    };
  }, [props.username]);

  return (
    <div>
      {error ? (
        <span>{error}</span>
      ) : (
        <ul>
          <li>{JSON.stringify(data)}</li>
          <li>{JSON.stringify(repos)}</li>
        </ul>
      )}
    </div>
  );
}
function App() {
  const [resp, setGitData] = useState({ data: null, repos: null });

  useEffect(() => {
    const fetchData = async () => {
      const respGlobal = await axios(
        `https://api.github.com/users/${username}`
      );
      const respRepos = await axios(
        `https://api.github.com/users/${username}/repos`
      );

      setGitData({ data: respGlobal.data, repos: respGlobal.data });
    };

    fetchData();
  }, []);

  console.log('render');
  if (resp.data) {
    console.log("d", resp.data, resp.repos);
  }

  return <h1>Hello</h1>;
}

he made some mistake here:
setGitData({ data: respGlobal.data, repos: respGlobal.data(respRepos.data //it should be respRepos.data});

Figured I'd take a stab at it because the above answer is nice, however, I like cleanliness.我想我会尝试一下,因为上面的答案很好,但是,我喜欢清洁。

import React, { useState, useEffect } from 'react'
import axios from 'axios'

const Test = () => {
    const [data, setData] = useState([])

    useEffect(() => {
        (async () => {
            const data1 = await axios.get('https://jsonplaceholder.typicode.com/todos/1')
            const data2 = await axios.get('https://jsonplaceholder.typicode.com/todos/2')
            setData({data1, data2})
        })()
    }, [])

    return JSON.stringify(data)
}

export default Test

Using a self invoking function takes out the extra step of calling the function in useEffect which can sometimes throw Promise errors in IDEs like WebStorm and PHPStorm.使用自调用函数useEffect了在useEffect调用函数的额外步骤,这有时会在 WebStorm 和 PHPStorm 等 IDE 中抛出 Promise 错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM