javascript Next.js中的客户端组件更改数据后更新服务器组件

t0ybt7op  于 2023-05-21  发布在  Java
关注(0)|答案(2)|浏览(316)

我还在想这件事。有没有人能建议在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一个新用户已经添加到集合中,以强制它显示一个新用户/更新的用户?

gev0vcfq

gev0vcfq1#

目前,将客户端组件更新的数据反映到服务器组件上的唯一方法是调用router.refresh(),其中router是在您向API发出请求后useRouter返回的值。正如你在官方的Next.js doc上看到的:
Next.js团队正在开发一个新的RFC,用于在Next.js中改变数据。此RFC尚未发布。目前,我们推荐以下模式:
您可以使用router.refresh()更改app目录中的数据。
他们给出了一个很好的例子,使用Todo List应用程序。我在下面添加了它,以便有一个更完整的线程。
让我们考虑一个列表视图。在服务器组件中,获取项目列表:

// app/page.tsx

import Todo from "./todo";
async function getTodos() {
  const res = await fetch("https://api.example.com/todos", { cache: 'no-store' });
  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 handleChange() {
    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={handleChange}
        disabled={isPending}
      />
      {todo.title}
    </li>
  );
}
wgeznvg7

wgeznvg72#

https://stackoverflow.com/a/75127011/17964403这对于在客户端进行变异是非常好的,但是如果你想在客户端使用输入进行搜索/过滤,并且想重新获取相同的数据,你可以这样做

const [searchterm, setSearchterm] = useState("");
const handleSearch = (e) => {
   e.preventDefault();
   if(!searchterm)return
   router.push(/home?search=`${searchterm}`)
}

在服务器组件中,您将接收到search param作为 prop ,查看search param是否存在,如果存在,则在fetch调用中传递该参数,您将获得过滤后的项目。

相关问题