使用React Hooks在不同页面中获取请求

马可·马扎伊

我正在使用React Hooks建立一个网站,并且有两个不同的页面(Workshops.js和Shows.js)从同一API提取数据,只是使用不同的参数(?type = 0和?type = 1)。一旦获取了数据,我就会映射结果(在那儿有一个可重用的组件会很好。请参见下面代码中的注释)。当用户单击表演或工作室时,他将被重定向到同一页面。

现在,代码可以正常工作了。有没有更优雅的方法来避免重复相同的代码?...类似于Angular中的Services?

谢谢!

这是Workshop.js。

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom'
import api from '../../maps/Api' 

const Workshops = () => {
    const [ workshops, setWorkshop ] = useState([])
    const [ isLoading, setIsLoading ] = useState(false)
    const [ error, setError ] = useState(null)
    const GET_URL = api.get.workshops /* http://someapi/workshops?type=0 */

    useEffect(() => {
        setIsLoading(true)
        fetch(GET_URL, {headers: {
            "Accept": "application/json",
            "Access-Control-Allow-Origin": "*"
        }})
        .then(res => {
            return (res.ok) ?  res.json() : new Error("Mistake!")
        })
        .then(workshops => {
            if(workshops.upcoming) {
                setWorkshop(workshops.upcoming);
            }
            setIsLoading(false);
        })
        .catch(error => {
            setError(error)
        })
    }, [GET_URL])

    if ( error ){ return <p>{ error.message }</p> }
    if ( isLoading ){
        return <p>Loading workshops...</p>
    }

    return(

        <main>
            <div className='content'>
                <div className='contentCol'>
                    <ul id='workshopBox'>
                    {
                        workshops.map( (workshop, i) => (
                            <li> // FROM HERE...
                                <div
                                    className='workshop-active'>
                                    <h2>{ workshop.title }</h2>
                                    <p>{ workshop.description }</p>
                                    <p>{ workshop.place }</p>
                                    <p>{ (new Date(workshop.date).toLocaleDateString("it-IT", {
                                            weekday: 'long',
                                            year: 'numeric',
                                            month: 'long',
                                            day: 'numeric'
                                          }))}</p>
                                    <p>{ (new Date(workshop.date).toLocaleTimeString("it-IT", {
                                            hour: '2-digit',
                                            minute: '2-digit',
                                            hour12: true
                                          }))}</p>
                                    <p> Full price { workshop.price_full + ', 00'} &euro; </p>
                                    <p> Early bird price { workshop.price_earlybirds + ', 00'} &euro; </p>
                                    <p>
                                    <Link to={`/workshops/${ workshop.id}`}>
                                        <button>Details</button>
                                    </Link>
                                    </p>
                                    <br/>
                                </div>
                            </li> //..to HERE I WOULD LIKE TO USE A REUSABLE COMPONENT
                            ))
                    }
                    </ul>
                </div>
            </div>
        </main>
        )
    }

export default Workshops

这是Shows.js

import React, { useState, useEffect } from 'react';
//import { Link } from 'react-router-dom'
import api from '../maps/Api'

const Spettacoli = () => {
    const [ shows, setShows ] = useState([])
    const [ isLoading, setIsLoading ] = useState(false)
    const [ error, setError ] = useState(null)
    const GET_URL = api.get.shows /* http://someapi/workshops?type=1 */

    useEffect(() => {
        setIsLoading(true)
        fetch(GET_URL, {headers: {
            "Accept": "application/json",
            "Access-Control-Allow-Origin": "*"
        }})
        .then(res => {
            return (res.ok) ?  res.json() : new Error("Mistake!")
        })
        .then(shows => {
            setShows(shows)
            setIsLoading(false)
        })
        .catch(error => {
            setError(error)
        })
    }, [GET_URL])


    return(
        <main>
            <div className='content'>
                <div className='contentCol'>
                    /* SAME INTERFACE AS WORKSHOP */

                </div>
            </div>
        </main>
        )
}

export default Shows
天空男孩

因此,您可以创建自定义钩子

function useMyDataFetch(GET_URL) {
    const [ data, setData ] = useState([])
    const [ isLoading, setIsLoading ] = useState(true)
    const [ error, setError ] = useState(null)

    useEffect(() => {
        let hasBeenAborted = false; // added
        setIsLoading(true)
        fetch(GET_URL, {headers: {
            "Accept": "application/json",
            "Access-Control-Allow-Origin": "*"
        }})
        .then(res => {
            return (res.ok) ?  res.json() : new Error("Mistake!")
        })
        .then(data => {
            if (hasBeenAborted) return; // added
            if(data.upcoming) {
                setData(data.upcoming);
            }
            setIsLoading(false);
        })
        .catch(error => {
            if (hasBeenAborted) return; // added
            setIsLoading(false); // added
            setError(error)
        });
        return () => { hasBeenAborted = true; } // added
    }, [GET_URL]);

    return { data, error, isLoading };
}

并在您的组件中使用它。

注意我用标记的行// addedhasBeenAborted允许我们对GET_URL同一组件由于任何原因而被更新的情况做出反应清理工作useEffect非常重要,因此我们避免出现竞争状况。

除了hasBeenAborted可以使用标志之外AbortController,我们仍然可以使用它来进入catch分支,并且需要进行额外if区分以区分请求是已取消还是实际失败。所以对我来说只是品味。

对于您的组件,它们将使用类似的钩子:

const Workshops = () => {
    const {isLoading, error, data: workshops} = useMyDataFetch(api.get.workshops);

    if ( error ){ return <p>{ error.message }</p> }
    if ( isLoading ){
        return <p>Loading workshops...</p>
    }

    return(
      // the same here
    );

}

export default Workshops

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在ASP.NET Web窗体中,如何使用“获取”请求调用页面方法

在React中使用setState的多个获取请求

使用React Native在获取请求中禁用重定向

React Native:使用组件状态获取请求

使用React Router在不同页面中渲染组件问题

使用Hooks在React中更新数组

如何使用请求从此页面获取数据?

React使用React Hooks从Router获取道具

Razor页面中的最佳实践:使用AJAX或Handlers处理发布/获取请求

React Hooks:在useEffect中获取数据

使用React Native Hooks

React Hooks中未使用的var

如何使用React Hooks在不同页面中显示嵌套路由?

如何使用Python中的请求从Reddit页面的帖子中获取所有图像链接

如何使用带有React Hooks的axios来发布请求?

如何修复Axios获取请求和React Hooks?

使用python请求获取所有页面

使用PHP从Curl或任何库中获取网站页面请求的所有链接

如何使用 Angular 中的 observable 获取 API http 请求的所有页面中的数据?

使用 Expo 在 React Native 中取消异步获取请求

如何使用 React Hooks 渲染不同的组件

使用 React 钩子取消 HTTP 获取请求

使用 axios 获取请求的结果填充对象(在 React js 中)

使用 React Hooks 的问题

使用 React 获取 cURL 请求

无法在嵌套在克隆对象中的数组上使用 map() 方法(获取 API)-React Hooks

在 React hooks 中获取输入值并打印

使用 React Hooks 从 YouTube API 获取数据

使用 hooks 时无法在 react 中获取 props