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

Next.js中'use server'服务端函数传参及数据处理最佳实践

问题解答

一、调用与数据处理的位置

  1. 触发调用时机:在搜索按钮的点击事件处理函数中,调用服务端的getData函数并传入搜索payload。
  2. 数据处理拆分:
    • 过滤逻辑:建议直接在服务端函数getData内完成(原因见下文最佳实践分析)。
    • 排序逻辑:因为排序字段存在客户端的useContext状态仓库中,有两种处理方式:
      • 方式一:将排序字段作为额外参数传给getData,在服务端完成过滤+排序后返回最终结果。
      • 方式二:先从服务端获取过滤后的数据,再在客户端结合useContext中的排序字段完成排序操作。

二、过滤逻辑放在服务端函数是否为最佳实践

这属于推荐的最佳实践,原因如下:

  • 减少数据传输量:仅返回符合过滤条件的数据,避免全量数据传输到客户端再过滤,节省带宽。
  • 扩展性更强:后续若将模拟数据替换为真实数据库查询,服务端过滤可直接对接数据库查询条件(如SQL的WHERE子句),无需大幅修改逻辑。
  • 数据安全性:若数据包含敏感内容,服务端过滤可避免敏感数据泄露至客户端。

修改后的服务端函数示例

"use server";

import { DATA } from "/constants/data";

interface IPAYLOAD {
  name: string;
  location: string[];
  startDate: Date;
  endDate: Date;
  sortField?: string; // 可选:服务端排序时新增的参数
  sortOrder?: "asc" | "desc";
}

export const getData = async (payload?: IPAYLOAD) => {
  if (!payload) return DATA;

  let filteredData = [...DATA];

  // 按名称模糊过滤
  if (payload.name) {
    filteredData = filteredData.filter(item =>
      item.name.toLowerCase().includes(payload.name.toLowerCase())
    );
  }

  // 按位置过滤
  if (payload.location.length > 0) {
    filteredData = filteredData.filter(item =>
      payload.location.includes(item.location)
    );
  }

  // 按日期范围过滤(假设数据项包含date字段)
  if (payload.startDate && payload.endDate) {
    filteredData = filteredData.filter(item => {
      const itemDate = new Date(item.date);
      return itemDate >= payload.startDate && itemDate <= payload.endDate;
    });
  }

  // 可选:服务端排序逻辑
  if (payload.sortField) {
    filteredData.sort((a, b) => {
      if (payload.sortOrder === "asc") {
        return a[payload.sortField] > b[payload.sortField] ? 1 : -1;
      } else {
        return a[payload.sortField] < b[payload.sortField] ? 1 : -1;
      }
    });
  }

  return filteredData;
};

客户端调用示例(React)

import { useContext, useState } from "react";
import { getData } from "/path/to/your/server-function";
import { SortContext } from "/path/to/your/context";

export const SearchComponent = () => {
  const { sortField, sortOrder } = useContext(SortContext);
  const [results, setResults] = useState([]);
  const [searchForm, setSearchForm] = useState({
    name: "",
    location: [],
    startDate: new Date(),
    endDate: new Date()
  });

  const handleSearch = async () => {
    const filteredData = await getData({
      ...searchForm,
      sortField,
      sortOrder
    });
    setResults(filteredData);
  };

  return (
    <div>
      <input
        type="text"
        value={searchForm.name}
        onChange={(e) => setSearchForm({...searchForm, name: e.target.value})}
        placeholder="输入名称"
      />
      {/* 其他表单控件(如位置选择、日期选择)省略 */}
      <button onClick={handleSearch}>搜索</button>
      <ul>
        {results.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:37:26