Как получить данные из вложенных массивов при помощи метода 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 шт):

Автор решения: SwaD

У вас есть массив объектов(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.

→ Ссылка