Next.js中'use server'服务端函数传参及数据处理最佳实践
问题解答
一、调用与数据处理的位置
- 触发调用时机:在搜索按钮的点击事件处理函数中,调用服务端的
getData函数并传入搜索payload。 - 数据处理拆分:
- 过滤逻辑:建议直接在服务端函数
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
相关产品推荐
相关产品推荐

