axios 第一次加载useEffect hock时显示多次调用API时出错

bqjvbblv  于 2023-04-06  发布在  iOS
关注(0)|答案(4)|浏览(173)

我是React.js的新手第一次加载代码显示错误,当我评论这部分{data.advice}并运行它时,它向我显示html,它还调用API 2次,它在重新加载时给出错误。如何修复它?

import { Box, Button, Card, CardActions, CardContent, Container, Typography } from '@mui/material';
import axios from 'axios';
import React, { useEffect, useState } from 'react';

const Advice = () => {
    const [data, setData] = useState(null);
    const clicked = () => {
        callAPI();
    }
    const callAPI = () => {
        axios.get('https://api.adviceslip.com/advice')
            .then(respone => {
                setData(respone.data.slip)
                console.log(respone.data.slip);
            })
            .catch((error) => {
                console.log(error);
            })
    }
    useEffect(() => {
        callAPI();
    }, [])
    return (
        <Box>
            <Container>
                <Typography variant='h2' sx={{ textAlign: "center" }}>Advice App</Typography>
                <Card sx={{ maxWidth: 500, margin: "10px auto", display: "block", textAlign: "center" }}>
                    {/* <CardMedia
                        sx={{ height: 140 }}
                        image="/static/images/cards/contemplative-reptile.jpg"
                        title="green iguana"
                    /> */}
                    <CardContent>
                        <Typography gutterBottom variant="h5" component="div">
                            Advice of the Day
                        </Typography>
                        <Typography variant="body2" color="text.secondary">
                            {data.advice}
                        </Typography>
                    </CardContent>
                    <CardActions>
                        <Button size="small" onClick={clicked}>Share</Button>
                        <Button size="small">Learn More</Button>
                    </CardActions>
                </Card>
            </Container>
        </Box>
    );
};

export default Advice;

https://codesandbox.io/s/cool-wildflower-p7k6ee?file=/src/App.js
任何帮助将不胜感激

pxy2qtax

pxy2qtax1#

正如评论中提到的
你得到的错误,因为你的代码是试图打印建议属性的数据,甚至在它被初始化。你可以尝试下面的代码,以确保它会打印时,数据是存在的。

{data && data.advice}

发送两个API调用的可能原因可能是因为您的应用组件 Package 在<strict>标签中。这意味着react在严格模式下运行。这将调用您的效果两次,而react将仅在开发模式下执行。所以这很好。没什么可担心的。reference:React 18 strict mode causing component to render twice

9njqaruj

9njqaruj2#

在第一次运行时,您的data变量是null(来自useState(null)),因此尝试访问data.advice会触发错误,因为您无法访问null值的对象属性。
有很多方法可以解决这个问题,但最简单的两个(现在就完成你的工作)是:

  1. const [data, setData] = useState({ advice: null });-将data的初始值替换为一个对象。然后data.advice将在第一次运行时渲染null,并且什么都不可见。您也可以使用一个正在加载消息来代替null,如...{ advice: 'Loading...' });
    1.使用{data && data.advice || nulldata ? data.advice : null保护显示的表达式({data.advice}),无论您喜欢哪种。加载消息代替null也是可能的。
    双重网络调用可能是由于Advice组件在页面加载时被其包含组件渲染了两次(或自动重新渲染)(因此运行了useEffect钩子两次)。您需要进一步调试才能捕捉到这一点,为了帮助我们,您需要使用容器组件的代码更新您的问题,以便我们可以捕捉到问题。
hyrbngr7

hyrbngr73#

你在第一次渲染时得到一个错误的原因是因为你有“data”初始化为null。“data”是null,因此没有“advice”属性,你应该得到的错误是“Cannot read property of null”。
use Effect钩子在渲染后调用。
useEffect做什么?通过使用这个Hook,你告诉React你的组件需要在render之后做一些事情。React会记住你传递的函数(我们将其称为“effect”),并在执行DOM更新后调用它。在这个effect中,我们设置文档标题,但我们也可以执行数据获取或调用其他命令式API。
来源:https://legacy.reactjs.org/docs/hooks-effect.html
旁注:这些是过时的文档,但它们应该是正确的,关于这种行为。
@CodeThing提供的解决方案应该可以修复这个错误。它会检查“data”是否存在,如果不存在,它会立即返回false,并且不检查“data.advice”。
另一方面,你可以使用advice属性将数据初始化为object,并将其设置为空字符串:{建议:““}
希望这有帮助:)

ogsagwnx

ogsagwnx4#

因为你为数据设置了null,然后你试图把它作为一个 object 来访问。你应该使用一个条件。例如:

<Typography variant="body2" color="text.secondary">
      {data?.advice}
  </Typography>

相关问题