【问题标题】:Proper way to fetch from another component - ReactJS从另一个组件获取的正确方法 - ReactJS
【发布时间】:2021-11-22 12:04:53
【问题描述】:

我有一个可以正确获取数据的组件,但我想将它封装在一个助手中。我已经尝试了很多东西,但我被卡住了。

这是有效的组件:

export const Carousel = () => {

const [ lotteries, setLotteries ] = useState({});
const [ isLoading, setisLoading ] = useState(true);

useEffect(() => {
    
    async function fetchAPI() {
        const url = 'https://protected-sea-30988.herokuapp.com/https://www.lottoland.com/api/drawings;'
        let response = await fetch(url)
        response = await response.json()
        
        setLotteries(response)
        setisLoading(false)
        }
    
        fetchAPI()
}, [])

return (

    <>
        {
            isLoading ? (
                <span>loading</span>
            ) : (

            <Slider >
                {
                Object.keys(lotteries).map((lottery, idx) => {
                    return (
                        <Slide 
                            key={ idx }
                            title={ lottery }
                            prize={ lotteries[lottery].next.jackpot }
                            day={ lotteries[lottery].next.date.day }
                        />
                    )
                })
                }
            </Slider>
        )}
    </>
);}

这是迄今为止我尝试的最后一件事。这是没有 fetch 的组件

export const Carousel = () => {

const [ lotteries, setLotteries ] = useState({});
const [ isLoading, setIsLoading ] = useState(true);

useEffect(() => {
    
    getLotteries()
    setLotteries(response)
    setIsLoading(false)
      
}, [])

这就是我尝试封装获取的地方。

export const getLotteries = async() => {

    const url = 'https://protected-sea-30988.herokuapp.com/https://www.lottoland.com/api/drawings;'
    let response = await fetch(url)
    response = await response.json()

    return response;
    
}

我对 React 有点陌生,因此非常感谢任何帮助。非常感谢。

【问题讨论】:

    标签: javascript reactjs fetch fetch-api


    【解决方案1】:

    要从 getLotteries 助手获取获取的数据,您必须返回一个承诺

    export const getLotteries = async() => {
    const url = 'https://protected-sea- 
     30988.herokuapp.com/https://www.lottoland.com/api/drawings;'
    let response = await fetch(url)
    return  response.json()
    

    }

    并将其称为异步/等待

    useEffect(async() => {
    
    let response= await getLotteries()
    setLotteries(response)
    setIsLoading(false)
    
    }, [])
    

    【讨论】:

    • 行得通!即使它现在抛出警告“效果回调是同步的以防止竞争条件。将异步函数放在里面:useEffect(() => { async function fetchData() { // 你可以在这里等待 const response = await MyAPI.getData( someId); // ... } fetchData(); }, [someId]); // 或者 [] if effect 不需要 props 或 state " 所以最后要求获取组件内部的所有 fetch 而不是 helper . :(
    • 最后我可以避免它像我在下面的回答中那样编辑你的 useEffect。
    • useEffect(() => { const fetchLotteries = async () => { const data = await getLotteries(); setLotteries(data); setIsLoading(false) } fetchLotteries(); }, [] )
    【解决方案2】:

    如果您想将请求 URL 的逻辑分离到另一个辅助函数中,您可以创建一个自定义钩子。

    // customHook.js
    
    import { useEffect, useState } from 'react';
    
    export function useLotteries() {
      const [lotteries, setLotteries] = useState(null);
    
      useEffect(() => {
        fetch('https://protected-sea-30988.herokuapp.com/https://www.lottoland.com/api/drawings;')
          .then(response => response.json())
          .then(json => setLotteries(json));
      }, []);
    
      return lotteries;
    }
    
    // Carousel.js
    
    import { useLotteries } from "./customHook.js";
    
    export const Carousel = () => {
      const lotteries = useLotteries();
    
      if (lotteries) {
        return; /* Your JSX here! (`lotteries` is now contains all the request responses) */
      } else {
        return <Loader />; // Or just null if you don't want to show a loading indicator when your data hasn't been received yet.
      }
    };
    
    

    【讨论】:

    • 我已经尝试过了,但它会抛出“TypeError: Object is not iterable” :(
    • @Serralvaro 新代码应该可以工作
    • 非常感谢@Saiansh Singh
    猜你喜欢
    • 1970-01-01
    • 2017-08-19
    • 1970-01-01
    • 2017-06-10
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    相关资源
    最近更新 更多