Я новичок в 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
Любая помощь будет оценена
он работает и не показывает ошибку, но он вызывает API 2 раза
Перейдите к файлу index.js и посмотрите, заключено ли ваше приложение в <StrictMode>. Если это так, то в строгом режиме ваше приложение отображается дважды, и оно будет делать это только в режиме разработки. Так что это нормально. Не о чем беспокоиться. ссылка: stackoverflow.com/questions/72489140/…
При первом запуске ваша переменная data
имеет значение null
(из useState(null)
), поэтому попытка доступа к data.advice
вызывает ошибку, поскольку вы не можете получить доступ к свойствам объекта для значения null
.
Есть много способов исправить это, но 2 из самых простых (просто чтобы сделать свою работу сейчас):
const [data, setData] = useState({ advice: null });
- заменить начальное значение data
на объект. Тогда data.advice
отрендерит null
при первом запуске, и ничего не будет видно. У вас также может быть сообщение о загрузке вместо null
, как в ...{ advice: 'Loading...' });
.
защитите отображаемое выражение ({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 заставляет компонент рендериться дважды
Замените {data.advice} на {data && data.advice}. Причина двух вызовов API может заключаться в том, что вы можете запустить реагирующее приложение в строгом режиме.