Вы уже создали таблицы и написали функции на стороне сервера. Теперь соединим бэкенд с интерфейсом. В Convex это работает как «живая связь»: как только данные в базе меняются, экран пользователя обновляется сам.
Client Component: включаем интерактивность
В Next.js компоненты по умолчанию «серверные» — они быстрые, но не умеют реагировать на клики или использовать хуки. Чтобы подключить Convex, нам нужен Client Component.
Просто добавьте в самую первую строку файла директиву:
"use client";
Без этой строки браузер не сможет «слушать» обновления базы данных, и приложение выдаст ошибку.
Получаем данные через useQuery
React-хуки — это инструменты, которые «подцепляют» логику Convex к вашему интерфейсу. Главный хук для чтения данных — useQuery.
Забудьте о ручном обновлении страницы или сложных запросах. Convex берет это на себя.
Как это выглядит в коде
Мы вызываем хук и передаем ему путь к функции из папки convex.
import { useQuery } from "convex/react";
import { api } from "../../convex/_generated/api";
export function TaskList() {
// Подписываемся на данные.
// Переменная tasks обновится сама, если в базе что-то изменится.
const tasks = useQuery(api.tasks.get);
// Пока данные летят из облака, tasks будет undefined
if (tasks === undefined) {
return <p>Загрузка...</p>;
}
return (
<ul>
{tasks.map((task) => (
<li key={task._id}>{task.text}</li>
))}
</ul>
);
}
Важно: Если
useQueryвернулundefined, значит, данные еще загружаются. Всегда добавляйте проверку, чтобы пользователь не видел пустой экран.
Меняем данные через useMutation
Для действий (нажать кнопку, отправить форму) используйте хук useMutation. В отличие от чтения, мутация срабатывает только тогда, когда вы её вызовете.
import { useMutation } from "convex/react";
import { api } from "../../convex/_generated/api";
export function AddTaskButton() {
const createTask = useMutation(api.tasks.create);
const handleClick = async () => {
// Отправляем данные и ждем подтверждения
await createTask({ text: "Запустить стартап" });
console.log("Готово!");
};
return <button onClick={handleClick}>Добавить задачу</button>;
}
Мутации возвращают Promise, поэтому мы используем async/await. Это позволяет, например, очистить поле ввода сразу после того, как запись в базе подтверждена.
Почему это идеально для MVP?
Главная фишка связки React + Convex — реактивность.
- Вы вызываете
useMutation. - Данные в облаке меняются.
- Мгновенно обновляются все
useQueryу всех пользователей, у которых открыто приложение.
Вам не нужно писать код для синхронизации состояния — всё просто работает «из коробки». 🚀
Чек-лист: как подключить функцию
- В начале файла стоит
"use client". - Импортированы
useQueryилиuseMutationизconvex/react. - Импортирован объект
api. - Хук вызван внутри компонента.
- Для
useQueryдобавлена проверка наundefined.
Сейчас наш интерфейс выглядит как обычный текст. Чтобы ваш стартап выглядел профессионально и вызывал доверие, в следующей теме мы займемся Созданием интерфейса на компонентах shadcn/ui. Мы превратим сырые данные в красивые карточки и формы.