Я все еще пытаюсь обдумать этот сценарий. Может кто-нибудь подсказать, как правильно это сделать в Next.js 13?
Я отображаю список пользователей в серверном компоненте, например, так (используя MongoDB):
// UsersList.jsx
const UsersList = () => {
const users = await usersCollection.getUsers()
return (
<div>
{users.map(user) => <div>{user}</div>}
</div>
)
}
И на той же странице я также определил клиентский компонент для добавления пользователей:
// UsersEdit.jsx
'use client'
const UsersEdit = () => {
const handleAdd() => // calls POST to /api/users
return // render input + button
}
Оба отображаются вместе, как показано на странице серверных компонентов:
// page.jsx
const Users = () => {
return (
<div>
<UsersList />
<UsersEdit />
</div>
)
}
Как мне «перезагрузить» или «уведомить» UsersList
о том, что в коллекцию добавлен новый пользователь, чтобы принудительно отобразить нового пользователя/обновленного пользователя?
🤔 А знаете ли вы, что...
JavaScript позволяет создавать мобильные приложения для iOS и Android с использованием фреймворков, таких как React Native и NativeScript.
На данный момент единственный способ отобразить обновленные данные вашим клиентским компонентом на серверном компоненте — это вызвать router.refresh()
, где router
— это значение, возвращаемое useRouter
, после вашего запроса к API. Как вы можете прочитать в официальном документе Next.js :
Команда Next.js работает над новым RFC для изменения данных в Next.js. Этот RFC еще не опубликован. На данный момент мы рекомендуем следующий шаблон:
Вы можете изменить данные внутри каталога приложения с помощью
router.refresh()
.
И они привели замечательный пример, работая с приложением Todo List. Я добавил его ниже, чтобы иметь более полную тему.
Рассмотрим представление списка. Внутри вашего серверного компонента вы получаете список элементов:
// app/page.tsx
import Todo from "./todo";
async function getTodos() {
const res = await fetch("/api/todos");
const todos = await res.json();
return todos;
}
export default async function Page() {
const todos = await getTodos();
return (
<ul>
{todos.map((todo) => (
<Todo key = {todo.id} {...todo} />
))}
</ul>
);
}
Каждый элемент имеет свой клиентский компонент. Это позволяет компоненту использовать обработчики событий (например, onClick или onSubmit) для запуска мутации.
// app/todo.tsx
"use client";
import { useRouter } from 'next/navigation';
import { useState, useTransition } from 'react';
export default function Todo(todo) {
const router = useRouter();
const [isPending, startTransition] = useTransition();
const [isFetching, setIsFetching] = useState(false);
// Create inline loading UI
const isMutating = isFetching || isPending;
async function handleChangeEvent() {
setIsFetching(true);
// Mutate external data source
await fetch(`https://api.example.com/todo/${todo.id}`, {
method: 'PUT',
body: JSON.stringify({ completed: !todo.completed }),
});
setIsFetching(false);
startTransition(() => {
// Refresh the current route and fetch new data from the server without
// losing client-side browser or React state.
router.refresh();
});
}
return (
<li style = {{ opacity: !isMutating ? 1 : 0.7 }}>
<input
type = "checkbox"
checked = {todo.completed}
onChange = {handleChangeEvent}
disabled = {isPending}
/>
{todo.title}
</li>
);
}