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

如何不使用URL搜索参数实现客户端与服务端组件的搜索交互?

不使用URL搜索参数实现客户端输入传递给服务端组件的方案

服务端组件(Server Component)在服务器端渲染完成后就会发送给客户端,无法直接接收客户端的实时交互状态(比如输入框内容)。要实现需求,需要通过客户端触发服务端数据获取的方式来完成,以下是两种可行方案:


方案一:使用Server Actions(Next.js 13+ 推荐)

无需额外创建API路由,直接在组件内定义服务端动作,客户端调用它获取数据,同时支持输入变化自动触发搜索。

步骤1:定义Server Action

创建单独文件封装服务端数据获取逻辑,标记为服务端执行:

// actions.js
'use server';

export async function fetchData(query) {
  if (!query.trim()) return null;
  
  // 替换为你的服务端数据获取逻辑(比如调用数据库/外部API)
  const res = await fetch(`https://your-api-domain.com/search?query=${encodeURIComponent(query)}`, {
    cache: 'no-store', // 禁用缓存,确保每次获取最新结果
  });

  if (!res.ok) throw new Error('数据获取失败');
  return res.json();
}

步骤2:调整组件结构

客户端组件维护输入状态,输入变化时调用Server Action,并将结果传递给ClientDisplayComponent:

// 页面组件(客户端组件)
'use client';

import { useState, useEffect } from 'react';
import { fetchData } from './actions';
import ClientDisplayComponent from './ClientDisplayComponent';

export default function SearchPage() {
  const [query, setQuery] = useState('');
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(false);

  // 输入防抖,避免频繁请求
  useEffect(() => {
    const timer = setTimeout(async () => {
      if (!query.trim()) {
        setData(null);
        return;
      }

      setIsLoading(true);
      try {
        const result = await fetchData(query);
        setData(result);
      } catch (err) {
        console.error(err);
        setData(null);
      } finally {
        setIsLoading(false);
      }
    }, 300); // 300ms防抖延迟

    return () => clearTimeout(timer);
  }, [query]);

  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="输入搜索内容..."
      />

      {isLoading && <p>加载中...</p>}
      <ClientDisplayComponent data={data} />
    </div>
  );
}

// ClientDisplayComponent.js(保持客户端组件)
'use client';

export default function ClientDisplayComponent({ data }) {
  if (!data) return <p>请输入搜索内容</p>;
  
  return (
    <div>
      <h3>搜索结果</h3>
      <ul>
        {data.map(item => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}

方案二:使用API路由 + SWR(适合需要缓存的场景)

创建独立API路由处理数据请求,客户端用SWR库自动管理请求、缓存和重新获取,同样支持输入变化自动更新。

步骤1:创建API路由

// app/api/search/route.js
export async function GET(request) {
  const { searchParams } = new URL(request.url);
  const query = searchParams.get('query');

  if (!query?.trim()) {
    return new Response(JSON.stringify({ error: '缺少搜索关键词' }), { status: 400 });
  }

  // 服务端数据获取逻辑
  const res = await fetch(`https://your-api-domain.com/search?query=${encodeURIComponent(query)}`, {
    cache: 'no-store',
  });

  if (!res.ok) {
    return new Response(JSON.stringify({ error: '数据获取失败' }), { status: 500 });
  }

  const data = await res.json();
  return new Response(JSON.stringify(data), { status: 200 });
}

步骤2:客户端组件使用SWR

// 页面组件(客户端组件)
'use client';

import { useState } from 'react';
import useSWR from 'swr';
import ClientDisplayComponent from './ClientDisplayComponent';

// 定义请求函数
const fetcher = async (url) => {
  const res = await fetch(url);
  if (!res.ok) throw new Error('请求失败');
  return res.json();
};

export default function SearchPage() {
  const [query, setQuery] = useState('');

  // SWR自动监听query变化,发起请求并处理缓存
  const { data, error, isLoading } = useSWR(
    query ? `/api/search?query=${encodeURIComponent(query)}` : null,
    fetcher,
    { debounce: 300 } // 300ms防抖
  );

  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="输入搜索内容..."
      />

      {isLoading && <p>加载中...</p>}
      {error && <p>获取数据失败,请重试</p>}
      <ClientDisplayComponent data={data} />
    </div>
  );
}

// ClientDisplayComponent.js 同方案一

关键说明

  • 服务端组件无法直接接收客户端实时状态,必须通过客户端触发服务端数据获取的方式实现交互
  • 防抖处理:设置300ms延迟,避免每次输入字符都发起请求,提升性能
  • ClientDisplayComponent保持客户端组件,直接接收数据完成渲染

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 00:42:33