You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:21:20