Multiple fetch data axios with React Hooks

前端 未结 4 1891
忘掉有多难
忘掉有多难 2021-01-03 13:53

I would like to get global information from Github user and his repos(and get pinned repos will be awesome). I try to make it with async await but It\'s is correct? I\'ve go

相关标签:
4条回答
  • 2021-01-03 13:57

    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>
      );
    }
    
    0 讨论(0)
  • 2021-01-03 14:13
    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});
    
    0 讨论(0)
  • 2021-01-03 14:16

    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.

    0 讨论(0)
  • 2021-01-03 14:18

    Multiple state updates are batched but but only if it occurs from within event handlers synchronously and not setTimeouts or async-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 liek

    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

    0 讨论(0)
提交回复
热议问题