bounty将在6天内到期。回答此问题可获得+100声望奖励。lost_in_the_source希望引起更多关注这个问题。
我有一个受保护的 Jmeter 板页面,其中包含评论列表。当添加新评论时,我想刷新页面。但是,这并不起作用。具体来说,useRouter().refresh什么也不做。我有一个显示在 Jmeter 板页面上的AddReview组件。它是一个按钮,当点击时,触发一个允许用户输入评论数据的模态。
下面是AddReview组件的代码:
"use client";
import { AiOutlinePlus } from 'react-icons/ai';
import Modal from './Modal.js';
import { useState } from 'react';
import { addReview, getAllReviews } from '/api';
import { useRouter } from "next/navigation";
import Router from 'next/navigation';
import { useSession } from 'next-auth/react';
import { v4 as uuidv4 } from 'uuid';
export default function AddReview()
{
const { data: session } = useSession();
const router = useRouter();
const [modalOpen, setModalOpen] = useState(false);
const [newContentCreatorName, setNewContentCreatorName] = useState("");
const [newRating, setNewRating] = useState("");
const [newText, setNewText] = useState("");
const handleSubmitNewTodo = async (e) => {
e.preventDefault();
// API to add review
await addReview({
id: uuidv4(),
contentCreatorName: newContentCreatorName,
rating: newRating,
text: newText,
owner: session.user.email,
});
setNewContentCreatorName("");
setNewRating("");
setNewText("");
setModalOpen(false);
router.refresh(); // refresh page to show new item in ReviewList
};
return (
<div>
<button
onClick={() => setModalOpen(true)}
className="btn btn-primary w-full">
Add new review <AiOutlinePlus className="ml-2" size={20}/>
</button>
<Modal modalOpen={modalOpen} setModalOpen={setModalOpen}>
<form onSubmit={handleSubmitNewTodo} className="w-full max-w">
<h3 className="font-bold text-lg mb-6 text-center">Add review</h3>
<div>
<input
value={newContentCreatorName}
onChange={e => setNewContentCreatorName(e.target.value)}
type="text"
placeholder="Content creator name"
className="block input input-bordered w-full mb-4" />
<input
value={newRating}
onChange={e => setNewRating(e.target.value)}
type="number"
placeholder="Rating (out of 5)"
className="block input input-bordered w-full mb-4" />
<input
value={newText}
onChange={e => setNewText(e.target.value)}
type="text"
placeholder="Review"
className="block input input-bordered w-full mb-4" />
<button className="btn" type="submit">Submit</button>
</div>
</form>
</Modal>
</div>
);
}
我使用会话对象,这样我就可以在将每个评论添加到数据库时记录其所有者/作者。在Dashboard页面上,还有一个会话对象,用于验证用户是否登录。下面是 Jmeter 板页面的代码。
"use client";
import AddReview from '../components/AddReview';
import ReviewList from '../components/ReviewList';
import { getAllReviews } from '/api';
import { use } from 'react';
import { useSession } from "next-auth/react";
const _reviews = getAllReviews(); // API to fetch reviews
export default function Dashboard()
{
const reviews = use(_reviews);
console.log(reviews);
const { data: session, status } = useSession({
required: true,
});
if (status === "loading")
return <div>Session is loading...</div>;
return (
<>
<div className="text-center my-5 flex flex-col gap-4">
<h1 className="text-2xl font-bold">Yelper</h1>
<AddReview />
</div>
{/* A component showing list of reviews (should be rerendered to reflect new review added) */}
<ReviewList reviews={reviews} email={session?.user.email} />
</>
);
}
我应该怎么做才能让useRouter().refresh函数真正刷新页面?
编辑:这里是我调用的函数,用于添加新的评论,以防提供更多的上下文:
export async function addReview(review)
{
const res = await fetch(`${baseUrl}/reviews`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(review).trim()
});
const newReview = await res.json();
return newReview;
}
2条答案
按热度按时间yi0zb3m41#
您的 Jmeter 板页面没有刷新,因为您使用的客户端组件不涉及任何服务器端数据获取。这是基于Next.js documentation的预期行为:
router.refresh()
:刷新当前路由。向服务器发出新请求、重新获取数据请求并重新呈现服务器组件。客户端将合并更新后的React服务器组件有效载荷,而不会丢失未受影响的客户端React(例如useState
)或浏览器状态(例如滚动位置)。根据您当前的实现,您只在初始页面呈现时获取一次评论列表。
您可以通过几种不同的方式实现所需的行为。
1.将 Jmeter 板页面重构为服务器组件并获取数据服务器端-https://nextjs.org/docs/app/building-your-application/data-fetching/fetching
1.以状态(
useState
)存储评论列表,并在添加新评论时重新获取数据。希望这能帮上忙。
u5i3ibmn2#
我认为这是因为你有一个服务器组件,它呈现客户端组件
AddReview
。当你调用router.refresh
时,你应该告诉服务器组件发出一个新的请求并获取最新的数据。为此,使用useTransitionHook
。fetch
请求被缓存。您可能需要使用no-store
选项来始终获取最新数据this explains
useTransition
在React 18之前,渲染是同步的。这意味着一旦React开始渲染,在它完成渲染组件之前,没有任何东西可以阻止它。但是,对于并发渲染,React可以暂停渲染并稍后继续,或者完全中止渲染。这是一个重要的新实现,使我们能够为用户提供更流畅的用户体验。
我们可以使用useTransition钩子来告诉React,某个状态更改将导致昂贵的渲染。React将降低这种状态更改的优先级,允许其他渲染更快地进行,提供一个响应非常快的UI。这种昂贵的渲染被称为过渡更新,应该立即发生的渲染被称为紧急更新。通常,键入、点击和按下被视为紧急更新,因为它们应该为用户提供即时响应,以确保良好的用户体验。