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

Next.js:如何在客户端组件用useSearchParams构建URL并获取服务端数据?

解决方案

方案1:使用React useEffect + useState处理客户端数据请求

在客户端组件中,不能直接在组件顶层使用async/await,但可以在useEffect钩子内部调用异步函数,配合useState管理数据、加载状态和错误信息:

'use client';

import { useSearchParams } from 'next/navigation';
import { useState, useEffect } from 'react';

export default function SearchResults() {
  const searchParams = useSearchParams();
  const searchValue = searchParams.get('query');
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchFilms = async () => {
      if (!searchValue) return;
      setLoading(true);
      try {
        const url = `${process.env.NEXT_PUBLIC_REQUEST_URL}${searchValue}`;
        const response = await fetch(url);
        if (!response.ok) throw new Error('请求失败');
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchFilms();
  }, [searchValue]);

  if (loading) return <div>加载中...</div>;
  if (error) return <div>错误:{error}</div>;
  if (!data) return <div>无搜索结果</div>;

  return <div>展示数据:{JSON.stringify(data)}</div>;
}

方案2:使用SWR/React Query等数据请求库

这类库封装了客户端数据请求的逻辑,自动处理缓存、加载、错误状态,无需手动编写useEffect:

以SWR为例:

  1. 先安装依赖:
npm install swr
  1. 组件中使用:
'use client';

import { useSearchParams } from 'next/navigation';
import useSWR from 'swr';

const fetcher = async (url) => {
  const response = await fetch(url);
  if (!response.ok) throw new Error('请求失败');
  return response.json();
};

export default function SearchResults() {
  const searchParams = useSearchParams();
  const searchValue = searchParams.get('query');
  const url = searchValue ? `${process.env.NEXT_PUBLIC_REQUEST_URL}${searchValue}` : null;

  const { data, error, isLoading } = useSWR(url, fetcher);

  if (isLoading) return <div>加载中...</div>;
  if (error) return <div>错误:{error.message}</div>;
  if (!data) return <div>无搜索结果</div>;

  return <div>展示数据:{JSON.stringify(data)}</div>;
}

方案3:拆分组件,客户端传参给服务端组件

将组件拆分为两部分:客户端组件负责获取URL参数,服务端组件负责数据请求。客户端组件可以导入服务端组件,并将searchValue作为props传递:

客户端组件(client-component.jsx):

'use client';

import { useSearchParams } from 'next/navigation';
import ServerDataFetcher from './server-data-fetcher';

export default function SearchWrapper() {
  const searchParams = useSearchParams();
  const searchValue = searchParams.get('query');

  return <ServerDataFetcher searchValue={searchValue} />;
}

服务端组件(server-data-fetcher.jsx):

// 无需加'use client',默认是服务端组件
export default async function ServerDataFetcher({ searchValue }) {
  if (!searchValue) return <div>无搜索关键词</div>;

  // 服务端组件支持顶层await,可直接发起请求
  const url = `${process.env.REQUEST_URL}${searchValue}`; // 此处可使用非NEXT_PUBLIC前缀的环境变量,更安全
  const response = await fetch(url);
  if (!response.ok) throw new Error('请求失败');
  const data = await response.json();

  return <div>展示数据:{JSON.stringify(data)}</div>;
}

注意事项:

  • 服务端组件中的fetch默认会缓存请求,若需要禁用缓存可配置{ cache: 'no-store' }或使用revalidate选项。
  • 服务端组件无法直接访问浏览器API,但可通过客户端组件传递所需参数。

内容的提问来源于stack exchange,提问作者Gevorg Martirosyan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:55:58