解决 Next.js + React 接口重复请求问题
在 Next.js 应用中,你可能会遇到 API 请求被发送两次的情况。以下是常见原因和解决方案:
1. 开发模式下 StrictMode 的影响
原因
Next.js 默认启用 React 的 StrictMode,在开发环境下会故意渲染两次组件以帮助发现潜在问题。
解决方案
// next.config.js
module.exports = {
reactStrictMode: false, // 关闭严格模式
}
或者仅在生产环境构建时保留:
// next.config.js
module.exports = {
reactStrictMode: process.env.NODE_ENV === 'production',
}
2. useEffect 依赖项问题
错误示例
useEffect(() => {
fetch('/api/data'); // 会触发多次
});
正确做法
useEffect(() => {
const fetchData = async () => {
const res = await fetch('/api/data');
const data = await res.json();
// 处理数据
};
fetchData();
}, []); // 空依赖数组确保只运行一次
3. 页面渲染和预取导致的重复请求
原因
Next.js 会自动预取页面链接,可能导致 API 被调用多次。
解决方案
// 禁用特定链接的预取
<Link href="/some-page" prefetch={false}>
不预取的链接
</Link>
4. 自定义 App 中的重复初始化
错误示例
// _app.js
function MyApp({ Component, pageProps }) {
fetch('/api/init'); // 会在每次路由变化时调用
return <Component {...pageProps} />;
}
正确做法
// _app.js
function MyApp({ Component, pageProps }) {
useEffect(() => {
fetch('/api/init');
}, []); // 只运行一次
return <Component {...pageProps} />;
}
5. API 路由缓存策略
在 API 路由中添加缓存头可以减少重复请求的影响:
// pages/api/data.js
export default function handler(req, res) {
res.setHeader('Cache-Control', 's-maxage=10, stale-while-revalidate=59');
res.status(200).json({ data: 'your data' });
}
6. 使用请求去重库
安装 axios
并使用请求拦截器:
npm install axios
import axios from 'axios';
const api = axios.create();
const pendingRequests = new Map();
api.interceptors.request.use(config => {
const requestId = `${config.method}-${config.url}`;
if (pendingRequests.has(requestId)) {
return Promise.reject(new Error('Duplicate request'));
}
pendingRequests.set(requestId, true);
config.requestId = requestId;
return config;
});
api.interceptors.response.use(response => {
const requestId = response.config.requestId;
pendingRequests.delete(requestId);
return response;
});
7. 检查浏览器插件
某些浏览器插件(如 React Developer Tools、Redux DevTools)可能会导致额外的请求,尝试在无痕模式下测试。
验证解决方案
- 检查网络请求是否仍然重复
- 确认只在生产环境下保留 StrictMode
- 确保所有 useEffect 都有正确的依赖数组
通过这些方法,你应该能够有效减少或消除 Next.js 应用中的重复 API 请求问题。