重新渲染我的数据当它在下一个13中发生变化时?

huangapple go评论65阅读模式
英文:

How do re-render my data when it's changed in next 13?

问题

如何在将已获取的数据作为 props 传递时,在 next-13 中重新渲染数据?
我试图在我的 TaskList 组件内部(使用 useEffect?)重新渲染在布局中获取的 tasks.data,当我从另一个组件发送 PUT 请求时。

我尝试设置 cache: no-store,但仍然需要刷新页面才能看到更改。

布局:

import TaskList from "@/components/tasks/TaskList";
import SetTaskForm from '@/components/tasks/SetTaskForm';
import { getAllTasks } from "@/utils/actions";

export default async function RootLayout({
  children
}: {
  children: React.ReactNode;
}) {
  const tasks = await getAllTasks()
  return (
    <html lang='en'>
      <body>
        <main>{children}
          <SetTaskForm />
          <TaskList tasks={tasks} />
        </main>
      </body>
    </html>
  );
}

TaskList:

import { TasksProps } from "@/types/taskTypes";
import Task from "./Task";
import { Suspense, useEffect } from "react";

export default function TaskList({ tasks }: TasksProps) {
  useEffect(() => {

  }, [tasks])
  return (
    <section className="py-9 flex flex-col justify-center">
      <h2 className="text-xl font-semibold mt-6 border-b pb-1 text-center">Tasks</h2>
      <Suspense fallback={<div>Loading...</div>}>
        <ul className="flex flex-col mx-3">
          {tasks?.data?.map((task: TaskProps) => (
            <li key={task.id}>
              <Task 
                key={task._id}    
                title={task.title} 
                body={task.body} 
                bgColor={task.bgColor}
                isCollapsed={task.isCollapsed}
                isCompleted={task.isCompleted}
              />
            </li>
          ))}
        </ul>
      </Suspense>
    </section>
  )
}

Task:

import { deleteTask, toggleCollapseTask, toggleCompletedTask } from "@/utils/actions";
import { TaskProps } from "@/types/taskTypes";
import 'material-icons/iconfont/material-icons.css';
import { useState } from "react";

export default function Task({ id, title, body, isCollapsed, bgColor, isCompleted }: TaskProps) {
  const [collapsed, setCollapsed] = useState(isCollapsed)
  const [completed, setCompleted] = useState(isCompleted)
  const handleCollapse = () => {
    setCollapsed(!collapsed)
    toggleCollapseTask(title, collapsed)
  }
  const handleCompleted = () => {
    setCompleted(!completed)
    toggleCompletedTask(title, completed)
  }
  return (
    <section>
      <div>
        <h1>{title}</h1>
        <span 
          onClick={e => deleteTask(title)}
        >delete</span>
      </div>
      <div>
        <span onClick={handleCollapse}>expand_more</span>
        {!collapsed && <a>{body}</a>}
      </div>
    </section>
  );
}

路由:

import { PrismaClient } from "@prisma/client";
import { NextResponse}  from "next/server";

const prisma = new PrismaClient()

export async function GET(request: Request) {
  const data = await prisma.tasks.findMany()
  return NextResponse.json({ data })
}

动作:

export async function getAllTasks() {
  const res = await fetch("http://localhost:3000/api/getAllTasks");
  if (!res.ok) {
    throw new Error("Failed to fetch data");
  }
  return res.json();
}

希望这可以帮助你的代码。如果你有任何问题或需要进一步的帮助,请随时提问。

英文:

How do I go about re-rendering my already fetched data in next-13 when passed as props?
I'm trying to get tasks.data which is fetched in the layout to rerender (useEffect?) inside of my TaskList component when I send a PUT request from another component.

I have tried setting cache: no-store but still have to refresh the page to see changes.

layout:

import TaskList from &quot;@/components/tasks/TaskList&quot;;
import SetTaskForm from &#39;@/components/tasks/SetTaskForm&#39;;
import { getAllTasks } from &quot;@/utils/actions&quot;;

export default async function RootLayout({
  children
}: {
  children: React.ReactNode;
}) {
  const tasks = await getAllTasks()
  return (
    &lt;html lang=&#39;en&#39;&gt;
      &lt;body&gt;
        &lt;main&gt;{children}
          &lt;SetTaskForm /&gt;
          &lt;TaskList tasks={tasks} /&gt;
        &lt;/main&gt;
      &lt;/body&gt;
    &lt;/html&gt;
  );
}

TaskList:

&quot;use client&quot;
import { TasksProps } from &quot;@/types/taskTypes&quot;
import Task from &quot;./Task&quot;
import { Suspense, useEffect } from &quot;react&quot;;

export default function TaskList ({ tasks }: TasksProps) {
  useEffect(() =&gt; {

  }, [tasks])
  return (
    &lt;section className=&quot;py-9 flex flex-col justify-center&quot;&gt;
      &lt;h2 className=&quot;text-xl font-semibold mt-6 border-b pb-1 text-center&quot;&gt;Tasks&lt;/h2&gt;
      &lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;
        &lt;ul className=&quot;flex flex-col mx-3&quot;&gt;
          {tasks?.data?.map((task: TaskProps) =&gt; (
            &lt;li key={task.id}&gt;
              &lt;Task 
                key={task._id}    
                title={task.title} 
                body={task.body} 
                bgColor={task.bgColor}
                isCollapsed={task.isCollapsed}
                isCompleted={task.isCompleted}
              /&gt;
            &lt;/li&gt;
          ))}
        &lt;/ul&gt;
      &lt;/Suspense&gt;
    &lt;/section&gt;
  )
}

Task:

&quot;use client&quot; 

import { deleteTask, toggleCollapseTask, toggleCompletedTask } from &quot;@/utils/actions&quot;;
import { TaskProps } from &quot;@/types/taskTypes&quot;;
import &#39;material-icons/iconfont/material-icons.css&#39;
import { useState } from &quot;react&quot;;

export default function Task({ id, title, body, isCollapsed, bgColor, isCompleted }: TaskProps) {
  const [collapsed, setCollapsed] = useState(isCollapsed)
  const [completed, setCompleted] = useState(isCompleted)
  const handleCollapse = () =&gt; {
    setCollapsed(!collapsed)
    toggleCollapseTask(title, collapsed)
  }
  const handleCompleted = () =&gt; {
    setCompleted(!completed)
    toggleCompletedTask(title, completed)
  }
  return (
    &lt;section&gt;
      &lt;div&gt;
        &lt;h1&gt;{title}&lt;/h1&gt;
        &lt;span 
          onClick={e =&gt; deleteTask(title)}
        &gt;delete&lt;/span&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;span onClick={handleCollapse}&gt;expand_more&lt;/span&gt;
      {!collapsed &amp;&amp; &lt;a&gt;{body}&lt;/a&gt;}
      &lt;/div&gt;
    &lt;/section&gt;
  );
}

route:

import { PrismaClient } from &quot;@prisma/client&quot;;
import { NextResponse}  from &quot;next/server&quot;

const prisma = new PrismaClient()

export async function GET(request: Request) {
  const data = await prisma.tasks.findMany()
  return NextResponse.json({ data })
}

action:

&quot;use server&quot;;

export async function getAllTasks() {
  const res = await fetch(&quot;http://localhost:3000/api/getAllTasks&quot;
  );
  if (!res.ok) {
    throw new Error(&quot;Failed to fetch data&quot;);
  }
  return res.json();
}

Any help or tips on my code greatly appreciated

答案1

得分: 2

文档

> 布局是在多个页面之间共享的 UI。在导航时,
> 布局保留状态,保持交互,并且不重新渲染。

这就是布局的全部意义。它将防止组件不必要地重新渲染。由于布局不会重新渲染,您不会从服务器获取新鲜数据。您应该重新验证数据

fetch(&#39;https://...&#39;, { next: { revalidate: 10 } });
英文:

From docs

> A layout is UI that is shared between multiple pages. On navigation,
> layouts preserve state, remain interactive, and do not re-render.

this is the whole point of the layout. it will prevent unnecessary rerendering of the components. Since layout is not rerendered, you are not fetching the fresh data from the server. You should revalidate data

fetch(&#39;https://...&#39;, { next: { revalidate: 10 } });

huangapple
  • 本文由 发表于 2023年5月28日 07:52:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76349454.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定