#javascript #reactjs
Вопрос:
Я создаю приложение react, и у меня проблема. Всякий раз, когда я обновляю страницу, я получаю ошибку типа: статьи[(статьи.длина — 1)] не определена, и это происходит из-за параметра src. Я хочу отобразить изображения 3 новейших статей, которые я добавил на сервер json. Но если я изменю src, например, на»», и после этого я запущу сервер, все будет работать нормально. Я могу изменить значение src обратно на articles[(статьи.длина — 1)] и без обновления всего, как следует. Я думаю, проблема в том, что статьи компилируются до того, как они получат значение от сервера json, и я не знаю, как это можно исправить. Перепробовал множество способов, таких как получение сдачи, но ни один из них не сработал.
в ArticlesList.js
const ArticlesList = ({ articles }) => {
return (
<div className="whole">
{console.log(articles.length)}
<Carousel fade>
<Carousel.Item>
<img
className="d-block w-100"
src={articles[articles.length-1].img}
alt="First slide"
width="1100" height="400"
/>
<Carousel.Caption>
<h3>TESTESTESSTESTESTES</h3>
</Carousel.Caption>
</Carousel.Item>
<Carousel.Item>
<img
className="d-block w-100"
src={articles[articles.length-2].img}
alt="Second slide"
width="1100" height="400"
/>
<Carousel.Caption>
<h3>Second slide labelxd</h3>
</Carousel.Caption>
</Carousel.Item>
<Carousel.Item>
<img
className="d-block w-100"
src={articles[articles.length-3].img}
alt="Third slide"
width="1100" height="400"
/>
<Carousel.Caption>
<h3>Third slide label</h3>
</Carousel.Caption>
</Carousel.Item>
</Carousel>
<CardGroup className="articles">
{articles.map((article) => (
<Col xs={4} md={4} lg={4} key={article.id}>
<Article article={article}/>
</Col>
))}
</CardGroup>
</div>
)
}
и в App.js
function App() {
const [articles, setArticles] = useState([])
useEffect(() => {
const getArticles = async () =>{
const articlesFromServer = await fetchArticles()
setArticles(articlesFromServer)
}
getArticles()
}, [])
const fetchArticles = async () =>{
const res = await fetch(
'http://localhost:5000/articles')
const data = await res.json()
return data
}
return (
<Router>
<>
<Header />
<Route path='/' exact render={(props) => (
<>
<ArticleList articles={articles} />
</>
)} />
<Route path='/details/:id' exact component={ArticleDetails} />
</>
</Router>
);
}
Комментарии:
1. Можете ли вы подтвердить, что статьи внутри
ArticlesList
не являются неопределенными, когда вы передаете их в качестве параметра?2. Вы смотрите на визуализацию списка статей или списков статей? Ваше соглашение об именах меняет их местами.
3. Список статей ты прав, мой плохой
Ответ №1:
Когда вы обновляете страницу, приложение пытается получить данные с внутреннего сервера, но ваш компонент ArticleDetails
уже загружен. Поскольку articles
состояние является пустым массивом, оно будет возвращено articles[articles.length-x]
как undefined
(что, в свою очередь, приведет к необнаруженной ошибке articles[articles.length-x].img
).
Поэтому в таких случаях используйте необязательную цепочку следующим образом.
articles[articles.length-x]?.img
Полный код будет выглядеть следующим образом.
const ArticlesList = ({ articles }) => {
return (
<div className="whole">
{console.log(articles.length)}
<Carousel fade>
<Carousel.Item>
<img
className="d-block w-100"
src={articles[articles.length-1]?.img}
alt="First slide"
width="1100" height="400"
/>
<Carousel.Caption>
<h3>TESTESTESSTESTESTES</h3>
</Carousel.Caption>
</Carousel.Item>
<Carousel.Item>
<img
className="d-block w-100"
src={articles[articles.length-2]?.img}
alt="Second slide"
width="1100" height="400"
/>
<Carousel.Caption>
<h3>Second slide labelxd</h3>
</Carousel.Caption>
</Carousel.Item>
<Carousel.Item>
<img
className="d-block w-100"
src={articles[articles.length-3]?.img}
alt="Third slide"
width="1100" height="400"
/>
<Carousel.Caption>
<h3>Third slide label</h3>
</Carousel.Caption>
</Carousel.Item>
</Carousel>
<CardGroup className="articles">
{articles.map((article) => (
<Col xs={4} md={4} lg={4} key={article.id}>
<Article article={article}/>
</Col>
))}
</CardGroup>
</div>
)
}
Надеюсь, это решит вашу проблему.
Комментарии:
1. Большое спасибо! вау, я не знаю, как я это пропустил
Ответ №2:
Основное недоразумение, которое у вас есть, кроется внутри App
компонента. Вы предполагаете, что жизненный цикл React componentDidMount будет ожидать асинхронных вызовов (в вашем случае fetchArticles
).
Что происходит, так это то, что App
компонент будет монтироваться независимо от того, вернул ли ваш API нужные вам статьи. Поэтому каждый компонент, который не защищает от не определенного значения articles
, обречен на сбой с нулевым исключением.
Добавьте нулевые проверки для статей в этих компонентах.
Ответ №3:
Я не знаю, как реагировать, но я бы предложил это
Это основано на моем подходе в Vue и т. Д. Я бы проверил длину articles
, прежде чем делать что-либо, что зависело бы от того, есть ли там контент.
В вашей функции рендеринга не могли бы вы просто вставить if
, например , вот так:
const ArticlesList = ({ articles }) => {
let result = ""
if (articles amp;amp; articles.length >0){
result = ( // Put things for .length-1
)
}
if (articles amp;amp; articles.length >1){
result = ( // Put things for .length-2
)
}
if (articles amp;amp; articles.length >2){
result = ( // Put things for .length-3
)
}
return result
Пожалуйста, не кричите на меня, если это неправильный синтаксис реакции: я просто показываю вам принцип, который я бы использовал в Vue. 😎
Вы могли бы сделать это циклом, чтобы избежать повторения
Вам нужно только один раз указать, как отобразить статью:
result = ""
const last3articles = articles.slice(Math.max(articles.length-3,0)).reverse()
last3articles.forEach(article=>{
result = ........// the part for a single article.
})
Комментарии:
1. Это тоже правильно. Но допустим, если
length
меньше 2. Тогдаarticles[articles.length-3].img
это снова приведет к необнаруженной ошибке, верно ?2. Ах, я пропустил тот факт, что вы ссылались на различные индексы статей. Я обновил свое предложение
3. Это тоже работает! спасибо c: