React里用prefetch预加载数据总是延迟加载,怎么回事?
我在博客列表页用next/router的prefetch想预加载文章详情页,但每次点击链接还是看到明显的加载动画。代码写的是这样:
import { useEffect } from 'react';
import { useRouter } from 'next/router';
function ArticleList({ articles }) {
const router = useRouter();
useEffect(() => {
articles.forEach(article => {
router.prefetch(<code>/${article.slug}</code>);
});
}, []);
return (
<ul>
{articles.map(article => (
<li key={article.id}>
<a href={<code>/${article.slug}</code>}>{article.title}</a>
</li>
))}
</ul>
);
}
测试时发现:页面加载时控制台没有预加载请求,直到点击链接的瞬间才会看到所有文章的API请求。明明按照文档写了prefetch啊,是不是哪里没配置对?
prefetch的理解上。这个方法确实会预加载页面,但它预加载的只是页面本身(即.js文件),而不是文章详情页的数据。你看,
router.prefetch只是告诉浏览器“嘿,用户可能会访问这个页面,先把它的代码下载下来”。但文章详情页的数据通常是通过getStaticProps或getServerSideProps动态获取的,这部分不会被提前加载。所以当你点击链接时,仍然需要等待数据请求完成。解决办法有两种:
1. **静态生成所有文章详情页**
如果你的文章内容不经常变化,可以用
getStaticPaths和getStaticProps提前生成所有详情页。这样用户点击时就直接拿到现成的内容了。示例代码:
2. **手动提前加载数据**
如果不想用静态生成,也可以在列表页手动触发数据请求。比如在
useEffect里直接发起所有文章详情的请求,把结果存到全局状态(比如 Redux 或 Context)里。示例代码:
选哪种方式取决于你的业务场景。如果文章数量不多且更新频率低,第一种更推荐;如果文章很多或者动态性很强,第二种可能更适合。
最后别忘了调试看看,打开网络面板确认是否真的提前加载了资源。