【问题标题】:Axios request keeps returning twice undefined and twice the dataaxios请求不断返回两次未定义和两次数据
【发布时间】:2022-10-09 14:57:45
【问题描述】:

我正在尝试使用 Axios 在自定义 reactjs 挂钩上获取 api。我一直得到两倍的未定义响应,然后是成功获取数据的两倍。未定义破坏了我的应用程序。

顺便说一句,我正在从 randomuser api 获取。

import axios from "axios";
import { useState, useEffect } from "react"

export const useFetch = (url) => {
    const [loading, setLoading] = useState(false);
    const [data, setData] = useState([]);
    const [error, setError] = useState('')

    const getData = () => {
        setLoading(true)
        try {
            axios.get(url)
                .then(response => setData(response.data));
                setLoading(false)
          } catch (error) {
            setError(error)
          }
    };

    useEffect(() => {
        getData()
    }, [url])

    return {loading, data, error}
}

尝试在这里使用它并映射它

import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useFetch } from '../custom_hooks/useFetch';

const PersonDetails = () => {

    const { loading, data , error } = useFetch('https://randomuser.me/api?results=20');
    const { results } = data;
    const { id } = useParams();

    const [person, setPerson] = useState({})

    useEffect(() => {
        const newPerson = results?.find(person => person.login.uuid === parseInt(id))
        setPerson(newPerson)
        console.log(newPerson)
    }, [])

    return (
        <div>
            {person.name.first}
        </div>
    )
}

export default PersonDetails

这是我实际上正在尝试做的事情,但现在因为它是未定义的,我知道无法读取未定义的属性......

【问题讨论】:

  • 嗨 Liss,欢迎来到 Stack Overflow!你能提供一个MRE吗?
  • 使用loadingexport 来规避它(并在获取请求成功后将其设置为false)。
  • 不要将 await 与 .then 一起使用。钩子也不会等待异步函数在返回之前返回设置状态。
  • @madflow 我对重复调用更感兴趣。我认为loading 或未定义的问题是次要的。仍然是防止未定义的好方法,但我认为这不是根本问题
  • data 状态变量将在首次加载时未定义。您可以尝试将其设置为一个空数组作为初始值,例如 const [data, setData] = useState([]);,它可能会阻止它破坏您的应用程序,但如果没有更多详细信息,则很难进行故障排除。

标签: javascript reactjs axios fetch


【解决方案1】:

当效果运行时:

  1. setLoading(true)
  2. 发送 Ajax 请求
  3. setLoading(false)

    稍后,Ajax 响应会到达您:

    1. setData(response.data)

      由于您依赖loading 来确定是否设置了data,因此它会中断。

      你可以做两件事:

      1. setLoading(false) 移动到then 回调中,这样在你拥有setData(response.data) 之前它不会被设置
      2. 完全摆脱loading 并将您的逻辑基于dataundefined 或具有不同的值。

【讨论】:

  • 做了这个改变。我现在真正需要做的是在另一个组件中获取该数据并对其进行过滤,但我一直未定义。您可以查看该帖子,因为我现在对其进行了编辑。
【解决方案2】:
  1. 您应该在 useEffect 中定义 getData 函数或将其传递到依赖数组中并通过 usecallback 包装该函数以避免不必要的重新渲染。
  2. 您应该在取消的情况下使用 abortcontroller 并让清理功能生效。 (这种情况下最好在useeffect中定义getdata body)
        useEffect(() => {
            const controller = new AbortController();
            const getData = async () => {
               setLoading(true)
               try {
                    await axios.get(url, {signal: controller.signal})
                    .then(response => setData(response.data));
                   } catch (error) {
                    setError(error)
                   }
                }
            getData()
            return()=>controller.abort()
         },[url]}
    

    您可以在以下 url 中阅读有关使用钩子获取数据的更多信息,以及在哪里设置加载和其他需要的状态。 https://www.robinwieruch.de/react-hooks-fetch-data/

【讨论】:

    【解决方案3】:

    以防万一,这个解决方案帮助了我:https://github.com/axios/axios/issues/2825#issuecomment-883635938

    “我的问题是由 React 开发服务器引起的。 反应中的严格模式导致了问题! 我不得不删除严格模式 这样就解决了发送双重请求的问题! 严格模式检查仅在开发模式下运行。 文档:https://reactjs.org/docs/strict-mode.html "

    【讨论】:

      猜你喜欢
      • 2020-02-25
      • 1970-01-01
      • 2020-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多