Next.js 14客户端调用服务端函数获取数据的正确方式
实现方案
方案1:使用服务器组件(Next.js App Router 推荐)
如果你的项目基于Next.js 13+的App Router,最推荐的方式是把数据获取逻辑放在服务器组件中,再将数据传递给客户端组件渲染。服务器组件天然支持async/await,无需"use client"标识,完全避开客户端fetch的限制。
示例代码:
// app/users/page.tsx(默认是服务器组件,无需"use client") async function getUsers() { const res = await fetch('https://your-api-endpoint/users', { method: 'GET', // 可选:设置缓存重新验证时间,单位秒 next: { revalidate: 60 } }); if (!res.ok) throw new Error('获取用户数据失败'); return res.json(); } export default async function UsersPage() { const users = await getUsers(); return ( <ul> {users.map(user => ( <li key={user.id}>{user.email}, {user.id}</li> ))} </ul> ); }
如果需要在客户端组件中处理交互(比如筛选用户),可以将服务器组件获取的数据传入客户端组件:
// app/users/UsersList.tsx(客户端组件) 'use client'; import { useState } from 'react'; export default function UsersList({ users }) { const [filter, setFilter] = useState(''); const filteredUsers = users.filter(user => user.email.includes(filter)); return ( <> <input type="text" placeholder="按邮箱筛选" onChange={(e) => setFilter(e.target.value)} /> <ul> {filteredUsers.map(user => ( <li key={user.id}>{user.email}, {user.id}</li> ))} </ul> </> ); }
然后在服务器组件中引入客户端组件:
// app/users/page.tsx import UsersList from './UsersList'; async function getUsers() { // 同上的fetch逻辑 } export default async function UsersPage() { const users = await getUsers(); return <UsersList users={users} />; }
方案2:客户端组件中使用 useEffect(标准做法)
所谓“useEffect不佳应避免”通常指滥用(比如依赖设置错误、重复请求),但合理使用useEffect是客户端组件获取数据的标准方式,完全可行。
示例代码:
'use client'; import { useState, useEffect } from 'react'; export default function UsersList() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchUsers = async () => { try { const res = await fetch('https://your-api-endpoint/users', { method: 'GET' }); if (!res.ok) throw new Error('获取用户数据失败'); const data = await res.json(); setUsers(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchUsers(); }, []); // 空依赖数组表示仅在组件挂载时执行一次 if (loading) return <div>加载中...</div>; if (error) return <div>错误:{error}</div>; return ( <ul> {users.map(user => ( <li key={user.id}>{user.email}, {user.id}</li> ))} </ul> ); }
方案3:使用数据获取库(SWR/React Query,复杂场景推荐)
如果项目有更多数据需求(比如缓存、自动重新获取、分页),可以用SWR或React Query这类库,它们封装了数据获取的逻辑,比手动写useEffect更高效健壮。
以SWR为例:
先安装依赖:
npm install swr
客户端组件中使用:
'use client'; import useSWR from 'swr'; const fetcher = async (url) => { const res = await fetch(url, { method: 'GET' }); if (!res.ok) throw new Error('获取用户数据失败'); return res.json(); }; export default function UsersList() { const { data: users, error, isLoading } = useSWR('https://your-api-endpoint/users', fetcher); if (isLoading) return <div>加载中...</div>; if (error) return <div>错误:{error.message}</div>; return ( <ul> {users.map(user => ( <li key={user.id}>{user.email}, {user.id}</li> ))} </ul> ); }
内容的提问来源于stack exchange,提问作者Mirakul
相关产品推荐
相关产品推荐

