Как получить данные из вложенных массивов при помощи метода map?
На Laravel имеется 3 таблицы post - images - images_post.
Сделал связь многие ко многим, и при запросе в PostMAN результат такой
{
"id": 1,
"title": "recusandae",
"description": "Officiis voluptates sit amet id. Dignissimos enim recusandae nam velit. Minima eum non cum.",
"url_preview": "http://jast.com/",
"created_at": "2022-12-06T14:50:32.000000Z",
"updated_at": "2022-12-06T14:50:32.000000Z",
"images": [
{
"id": 1,
"img_path": "quae",
"created_at": "2022-12-06T14:50:32.000000Z",
"updated_at": "2022-12-06T14:50:32.000000Z",
"pivot": {
"post_id": 1,
"image_id": 1
}
}
]
},
То есть на Backend я сделал получается все правильно.
Но на Next.JS у меня возникла проблема с тем что я не могу получить данные из вложенной таблицы images.
Код из файла со списком постов
export const getStaticProps = async () => {
const response = await fetch("/api/blogs");
const data = await response.json();
console.log(response);
if (!data) {
return { notFound: true };
} else {
return { props: { blogs: data } };
}
};
const Blogs = ({ blogs }) => {
return (
<div className="page-blog">
<div className="page-blog-header">
<h3>Blog</h3>
<p>...</p>
</div>
<div className="page-blog-content">
{blogs &&
blogs.map(
({ id, title, description, url_preview, created_at, img_path }) => (
<div key={id} className="page-blogs-content-item">
<Link href={`/blog/${id}`}>
<h3>{title}</h3>
</Link>
<p>{description}</p>
<p>{url_preview}</p>
<div>
{blogs && blogs.images.map(i => (
<div key={i.id}>{i.img_path}</div>
))}
</div>
<small>{created_at}</small>
<Link href={`/blog/${id}`}>{description}</Link>
</div>
)
)}
</div>
</div>
);
};
Выдаёт ошибку TypeError: Cannot read properties of undefined (reading 'map'),
нашел что фикс ошибки это добавление к blogs && blogs.images?.map(... знака вопроса, но это всего лишь убирает ошибку. Как правильно вывести изображения к конкретному посту?
Ответы (1 шт):
У вас есть массив объектов(blogs), у каждого элемента которого есть ключ images, который так же представляет массив объектов.
Вам надо внутри первого .map() перебирать не весь blogs, а вложенный массив текущего элемента.
В вашем blogs.map добавим ключ images и будет методом .map() перебирать вложенный массив:
/**
* @typedef {Object} ImagesType
* @property {number} id
* @property {string} img_path
*/
/**
* @typedef {Object} BlogsType
* @property {number} id
* @property {string} title
* @property {string} description
* @property {string} url_preview
* @property {string} created_at
* @property {ImagesType[]} images
*/
/**
* @param {BlogsType[]} blogs
* @return {*}
* @constructor
*/
const Blogs = ({ blogs }) => {
return (
<div className="page-blog">
<div className="page-blog-header">
<h3>Blog</h3>
<p>...</p>
</div>
<div className="page-blog-content">
{blogs &&
blogs.map(
({ id, title, description, url_preview, created_at, images }) => (
<div key={id} className="page-blogs-content-item">
<Link href={`/blog/${id}`}>
<h3>{title}</h3>
</Link>
<p>{description}</p>
<p>{url_preview}</p>
<div>
{images && images.map(i => (
<div key={i.id}>{i.img_path}</div>
))}
</div>
<small>{created_at}</small>
<Link href={`/blog/${id}`}>{description}</Link>
</div>
)
)}
</div>
</div>
);
};
Ваша ошибка была в том, что вы обращались к массиву как к объекту. У массива blogs нет свойства images.