在首次加载时,`useEffect` 钩子显示了一个错误,多次调用 API。

huangapple go评论69阅读模式
英文:

On first Load useEffect hock Shows an error calling the api multiple time

问题

我是React.js的新手
首次加载代码时出现错误
当我注释掉这部分 {data.advice} 并运行时它显示给我HTML
它还调用API两次
在重新加载时出现错误如何修复
英文:

I'm new to React.js
On the First Time load Code shows an error
when i comment this part {data.advice} and run it shows me html
it also calls API 2 times
it gives an Error on Reload. how to fix it?

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

Any Help will be Appreciated

答案1

得分: 1

如评论中所述,

你遇到错误是因为你的代码在初始化数据之前就尝试打印数据的 advice 属性。你可以尝试下面的代码以确保只有在有数据时才打印。

{data && data.advice}

发送两个 API 调用的可能原因是你的应用组件被包裹在 <strict> 标签中。这意味着 React 正在以严格模式运行。这将导致你的效果函数被调用两次,而 React 只会在开发模式下这样做。所以没关系,不用担心。参考:链接

英文:

As mentioned in the comments,

You are getting error because your code is trying to print advice property of data even before it is initialised. you can try below code to make sure it will print when data is present.

{data &amp;&amp; data.advice}

The possible reason for sending two api calls might be because your app component is wrapped in &lt;strict&gt; tags. That means react is running in strict mode. This will call your effects twice and react will do that in dev mode only. So that is fine. Nothing to worry about. reference:
https://stackoverflow.com/questions/72489140/react-18-strict-mode-causing-component-to-render-twice

答案2

得分: 0

在第一次运行时,你的 data 变量是 null(来自 useState(null)),因此尝试访问 data.advice 会触发错误,因为你不能在 null 值上访问对象属性。

修复这个问题有很多方法,但其中两种最简单的方法(只是为了让你的工作继续进行)是:

  1. const [data, setData] = useState({ advice: null }); - 用一个对象替换 data 的初始值。然后在第一次运行时,data.advice 将呈现为 null,什么都不会显示。你也可以使用加载消息代替 null,如 ...{ advice: '加载中...' });

  2. 使用条件语句保护显示表达式({data.advice}),可以选择使用 {data && data.advice || null}data ? data.advice : null。再次,可以使用加载消息代替 null

双重网络调用可能是由于 Advice 组件在页面加载时被其包含组件呈现两次(或自动重新渲染),从而导致你的 useEffect 钩子运行两次。你需要进一步调试来捕获这个问题,为了我们帮助你,你需要更新你的问题,并提供包含组件代码,这样我们就可以找到问题。

英文:

On the first run, your data variable is null (from useState(null)) so then trying to access data.advice triggers an error since you cannot access object properties on a null value.

There are many ways of fixing this, but 2 of the most simple ones (just to get your job done now) are:

  1. const [data, setData] = useState({ advice: null }); - replace the initial value of data with an object. Then data.advice will render null on the first run, and nothing will be visible. You could also have a loading message instead of null, as in ...{ advice: &#39;Loading...&#39; });.

  2. guard the displayed expression ({data.advice}) using either {data &amp;&amp; data.advice || null or data ? data.advice : null, whichever you prefer. A loading message instead of null is again possible.

The double network call can be due to the Advice component being rendered twice (or re-rendered automatically) by its containing component on page load (thus running your useEffect hook twice). You need further debugging to catch that, and for us to help you'd need to update your question with the container component's code, so that we might catch the issue.

答案3

得分: 0

在第一次渲染时出现错误的原因是因为“data”被初始化为null。“data”是null,因此没有“advice”属性,你应该得到的错误是“无法读取null的属性”。

使用Effect钩子在渲染后调用。

> useEffect是做什么的?通过使用这个Hook,你告诉React在渲染后需要执行一些操作。React会记住你传递的函数(我们将其称为“effect”),并在执行DOM更新后稍后调用它。在这个effect中,我们设置了文档标题,但我们还可以执行数据获取或调用其他命令式API。

来源:
https://legacy.reactjs.org/docs/hooks-effect.html

旁注:这些是过时的文档,但在这种行为方面应该是正确的。

@CodeThing提供的解决方案应该可以修复错误。它检查“data”是否存在,如果不存在,它立即返回false,并且不检查“data.advice”。

另一种方法是将data初始化为具有advice属性并将其设置为空字符串的对象:{ advice: ""}

希望这有所帮助 在首次加载时,`useEffect` 钩子显示了一个错误,多次调用 API。

英文:

The reason you get an error on the first render is beacuse you have "data" initialised with null. "data" is null, thus there is no "advice" property and the error you should get is "Cannot read property of null".

The use Effect hook is called after the render.

> What does useEffect do? By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.

Source:
https://legacy.reactjs.org/docs/hooks-effect.html

Side Note: These are the outdated docs but they should be correct, regarding this behaviour.

The solution @CodeThing provided should fix the error. It checks if "data" exists, if its not it immediately returns false and doesnt check "data.advice".

On the other hand you could initialize data as object with the advice property and set it to an empty string: { advice: ""}

Hope this helps 在首次加载时,`useEffect` 钩子显示了一个错误,多次调用 API。

答案4

得分: 0

因为你将数据设置为 null,然后尝试将其作为 object 访问。
你应该使用条件。例如:

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

Because you set null for the data and then you are trying to access it as an object.
you should use a condition. e.g:

 &lt;Typography variant=&quot;body2&quot; color=&quot;text.secondary&quot;&gt;
      {data?.advice}
  &lt;/Typography&gt;

huangapple
  • 本文由 发表于 2023年3月31日 18:06:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75897260.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定