Как получать данные на серверных компонентах в Next.js?

Я изучаю информацию о получении данных с серверного компонента в Next.js, и нашел материал <a href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching" rel="nofollow">здесь</a>. У меня есть следующий компонент: 

<pre><code class="javascript">import classNames from "classnames/bind";
import style from './style.module.scss'
import Image from "next/image";
import ProductItem from "@/components/product-item";
import Link from "next/link";

const cn = classNames.bind(style)

const getData = async () => {
     const response = await fetch("http://localhost:9000/api/cart/qty");
     const qty = await response.json();
}

export default async function MainPage() {
    const data = await getData();
    return (
        &lt;div className={cn('main-page')}&gt;
            &lt;div className={cn('title-section')}&gt;
                &lt;div className={cn('title')}&gt;
                    &lt;p&gt;
                        Уникальные изделия кубачинских мастеров
                    &lt;/p&gt;
                    {/*{qty.qty}*/}
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div className={cn('features')}&gt;
                &lt;div className={cn('item')}&gt;
                    &lt;Image src={'/heart.png'} alt={'индивидуальный подход'} width={50} height={50}/&gt;
                    &lt;span&gt;Индивидуальный подход&lt;/span&gt;
                &lt;/div&gt;
                &lt;div className={cn('item')}&gt;
                    &lt;Image src={'/hot-air-balloon.png'} alt={'индивидуальный подход'} width={50} height={50}/&gt;
                    &lt;span&gt;Доставка по всей России&lt;/span&gt;
                &lt;/div&gt;
                &lt;div className={cn('item')}&gt;
                    &lt;Image src={'/diamond-ring.png'} alt={'индивидуальный подход'} w...<br/></pre>

Как правильно извлечь и отобразить полученные данные в этом компоненте?
  • 21 сентября 2024 г. 13:33
Ответы на вопрос 2
Ваше понимание получения данных с серверного компонента в Next.js верное, но вам немного нужно его доработать, чтобы корректно извлечь и отобразить полученные данные. Ваша функция `getData` должна возвращать данные, чтобы их можно было использовать в компоненте. 

Попробуем немного изменить ваш код:

```javascript
import classNames from "classnames/bind";
import style from './style.module.scss'
import Image from "next/image";
import ProductItem from "@/components/product-item";
import Link from "next/link";

const cn = classNames.bind(style)

const getData = async () => {
    const response = await fetch("http://localhost:9000/api/cart/qty");
    
    // Убедитесь, что ответ успешен
    if (!response.ok) {
        throw new Error('Ошибка сети');
    }
    
    const qty = await response.json();
    return qty; // Возвращаем полученные данные
}

export default async function MainPage() {
    const data = await getData(); // Получаем данные
    const qty = data.qty; // Извлекаем нужное значение
    
    return (
        <div className={cn('main-page')}>
            <div className={cn('title-section')}>
                <div className={cn('title')}>
                    <p>
                        Уникальные изделия кубачинских мастеров
                    </p>
                    {/* Отображаем количество */}
                    <p>Количество в корзине: {qty}</p>
                </div>
            </div>
            <div className={cn('features')}>
                <div className={cn('item')}>
                    <Image src={'/heart.png'} alt={'индивидуальный подход'} width={50} height={50}/>
                    <span>Индивидуальный подход</span>
                </div>
                <div className={cn('item')}>
                    <Image src={'/hot-air-balloon.png'} alt={'доставка'} width={50} height={50}/>
                    <span>Доставка по всей России</span>
                </div>
                <div className={cn('item')}>
                    <Image src={'/diamond-ring.png'} alt={'качество'} width={50} height={50}/>
                    <span>Высокое качество</span>
                </div>
            </div>
        </div>
    );
}
```

### Основные изменения
1. **Возвращение данных**: В функции `getData` добавлено `return qty;`, чтобы данные могли быть извлечены в компоненте.
2. **Проверка состояния ответа**: Добавлена проверка на успешность ответа с помощью `response.ok`. Если ответ не успешен, выбрасывается ошибка, которую вы можете обработать в UI (например, показать сообщение об ошибке).
3. **Отображение данных**: В компоненте `MainPage` добавлен JSX для отображения количества товаров в корзине.

Теперь после вызова `getData`, вы сможете корректно извлечь и отобразить `qty` на странице, и данные будут отображаться при рендере компонента.
У тебя getData() возвращает промис и ты его пытаешься зарендерить в jsx, из-за чего получаешь ошибку 

Вот так должно быть:

import classNames from "classnames/bind";
import style from './style.module.scss'
import Image from "next/image";
import ProductItem from "@/components/product-item";
import Link from "next/link";

const cn = classNames.bind(style)

const getData = async () => {
    const response = await fetch("http://localhost:9000/api/cart/qty");
    if (!response.ok) {
        throw new Error("Failed to fetch data");
    }
    return await response.json();
}

export default async function MainPage() {
    const data = await getData();

    return (
        <div className={cn('main-page')}>
            <div className={cn('title-section')}>
                <div className={cn('title')}>
                    <p>
                        Уникальные изделия кубачинских мастеров
                    </p>
                    {/* Используем полученные данные */}
                    <p>{data.qty}</p>
                </div>
            </div>
            <div className={cn('features')}>
                <div className={cn('item')}>
                    <Image src={'/heart.png'} alt={'индивидуальный подход'} width={50} height={50} />
                    <span>Индивидуальный подход</span>
                </div>
                <div className={cn('item')}>
                    <Image src={'/hot-air-balloon.png'} alt={'индивидуальный подход'} width={50} height={50} />
                    <span>Доставка по всей России</span>
                </div>
                <div className={cn('item')}>
                    <Image src={'/diamond-ring.png'} alt={'индивидуальный подход'} width={50} height={50} />
                    <span>300+ изделий</span>
                </div>
                <div className={cn('item')}>
                    <Image src={'/shopping-store.png'} alt={'индивидуальный подход'} width={50} height={50} />
                    <span>Наш магазин открыт с 2003 года</span>
                </div>
            </div>
            <div className={cn('products-catalog')}>
                {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].map((el) => (
                    <Link className={cn('product-item-link')} href={`/jewellery-catalog/${el}`} key={el}>
                        <ProductItem />
                    </Link>
                ))}
            </div>
        </div>
    )
}
Похожие вопросы