При первой загрузке useEffect hock Показывает ошибку многократного вызова API

Я новичок в 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.info(respone.data.slip);
            })
            .catch((error) => {
                console.info(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

Любая помощь будет оценена

Замените {data.advice} на {data && data.advice}. Причина двух вызовов API может заключаться в том, что вы можете запустить реагирующее приложение в строгом режиме.

CodeThing 31.03.2023 12:11

он работает и не показывает ошибку, но он вызывает API 2 раза

Shoaib Dev 31.03.2023 12:16

Перейдите к файлу index.js и посмотрите, заключено ли ваше приложение в <StrictMode>. Если это так, то в строгом режиме ваше приложение отображается дважды, и оно будет делать это только в режиме разработки. Так что это нормально. Не о чем беспокоиться. ссылка: stackoverflow.com/questions/72489140/…

CodeThing 31.03.2023 12:20
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
54
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

При первом запуске ваша переменная data имеет значение null (из useState(null)), поэтому попытка доступа к data.advice вызывает ошибку, поскольку вы не можете получить доступ к свойствам объекта для значения null.

Есть много способов исправить это, но 2 из самых простых (просто чтобы сделать свою работу сейчас):

  1. const [data, setData] = useState({ advice: null }); - заменить начальное значение data на объект. Тогда data.advice отрендерит null при первом запуске, и ничего не будет видно. У вас также может быть сообщение о загрузке вместо null, как в ...{ advice: 'Loading...' });.

  2. защитите отображаемое выражение ({data.advice}) с помощью {data && data.advice || null или data ? data.advice : null, в зависимости от того, что вы предпочитаете. Сообщение о загрузке вместо null снова возможно.

Двойной сетевой вызов может быть связан с тем, что компонент Advice отображается дважды (или автоматически повторно отображается) содержащим его компонентом при загрузке страницы (таким образом, ваш хук useEffect дважды запускается). Вам потребуется дальнейшая отладка, чтобы уловить это, и чтобы мы могли помочь, вам нужно обновить свой вопрос с кодом компонента контейнера, чтобы мы могли обнаружить проблему.

Причина, по которой вы получаете ошибку при первом рендеринге, заключается в том, что у вас есть «данные», инициализированные нулевым значением. «данные» имеют значение null, поэтому свойство «совет» отсутствует, и вы должны получить сообщение об ошибке «Невозможно прочитать свойство нулевого значения».

Хук use Effect вызывается после рендера.

Что делает useEffect? Используя этот хук, вы сообщаете React, что ваш компонент должен что-то сделать после рендеринга. React запомнит переданную вами функцию (мы будем называть ее нашим «эффектом») и вызовет ее позже после выполнения обновлений DOM. В этом случае мы устанавливаем заголовок документа, но мы также можем выполнять выборку данных или вызывать какой-либо другой императивный API.

Источник: https://legacy.reactjs.org/docs/hooks-effect.html

Боковое примечание: это устаревшие документы, но они должны быть правильными в отношении такого поведения.

Предоставленное решение @CodeThing должно исправить ошибку. Он проверяет, существуют ли «данные», если это не так, он немедленно возвращает false и не проверяет «data.advice».

С другой стороны, вы можете инициализировать данные как объект с помощью свойства совета и установить его в пустую строку: {совет: ""}

Надеюсь это поможет :)

Потому что вы устанавливаете null для данных, а затем пытаетесь получить к ним доступ как к объекту. вы должны использовать условие. например:

 <Typography variant = "body2" color = "text.secondary">
      {data?.advice}
  </Typography>
Ответ принят как подходящий

Как упоминалось в комментариях,

Вы получаете сообщение об ошибке, потому что ваш код пытается напечатать свойство совета данных еще до того, как оно будет инициализировано. вы можете попробовать приведенный ниже код, чтобы убедиться, что он будет печататься при наличии данных.

{data && data.advice}

Возможная причина отправки двух вызовов API может заключаться в том, что компонент вашего приложения заключен в теги <strict>. Это означает, что реакция работает в строгом режиме. Это дважды вызовет ваши эффекты, и реакция сделает это только в режиме разработки. Так что это нормально. Не о чем беспокоиться. ссылка: Строгий режим React 18 заставляет компонент рендериться дважды

Другие вопросы по теме