NextJS技术问题:如何根据当前日期分类展示演出数据
问题:用客户端日期将演出数据分为「即将举办」和「已结束」列表
我是NextJS及前端技术新手,现在遇到个问题:想把演出数据按访客访问页面时的客户端当前日期分成「即将举办」和「已结束」两个列表展示。试了服务端组件,但它只会用服务器日期(这是正常行为);换成客户端组件后,又拿不到数据。
客户端组件代码
"use client"; import { getConcerts } from "@/lib/api"; import { useEffect, useState } from "react"; export default function Counter() { const [count, setCount] = useState(0); const [date, setDate] = useState(new Date()); const [concert, setConcerts] = useState(null); // 注:这里变量名不匹配,应为concerts useEffect(() => { const interval = setInterval(() => { // 每秒更新一次日期 setDate(new Date()); }, 1000); const fetchData = async () => { setConcerts(await getConcerts()); }; fetchData(); return () => clearInterval(interval); }, []); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> <p>{date.toLocaleString()}</p>{" "} {/* 转换为易读的日期字符串 */} </div> ); }
数据获取代码(@/lib/api)
export async function getConcerts(): Promise<any> { const entry = await fetchGraphQL( `query { concertCollection { items { sys {id } titre evenement date information { json } } } } `) return extractConcerts(entry); } function extractConcerts(fetchResponse: any): any { const concerts = fetchResponse?.data?.concertCollection?.items ?? []; return concerts; }
解决方案
1. 修复变量名错误
原代码中const [concert, setConcerts]变量名不匹配,改成const [concerts, setConcerts],避免后续渲染时找不到数据。
2. 确保GraphQL请求能在客户端运行
如果fetchGraphQL是服务端专用实现(比如依赖Node环境变量),需要调整为客户端可调用的版本:
// 修改@/lib/api中的fetchGraphQL函数 async function fetchGraphQL(query: string) { const response = await fetch('你的GraphQL API地址', { method: 'POST', headers: { 'Content-Type': 'application/json', // 如需认证,添加对应Header,比如Bearer token }, body: JSON.stringify({ query }), }); return await response.json(); }
3. 按客户端日期过滤演出数据
拿到数据后,用客户端的date状态分割列表:
// 在组件内添加过滤逻辑 const upcomingConcerts = concerts?.filter(concert => { const concertDate = new Date(concert.date); // 统一时区后比较,避免时区差异导致判断错误 return concertDate >= new Date(date.setHours(0,0,0,0)); }) ?? []; const pastConcerts = concerts?.filter(concert => { const concertDate = new Date(concert.date); return concertDate < new Date(date.setHours(0,0,0,0)); }) ?? [];
4. 渲染两个列表
在组件的返回部分添加列表渲染:
return ( <div> <p>当前时间:{date.toLocaleString()}</p> <h2>即将举办的演出</h2> <ul> {upcomingConcerts.map(concert => ( <li key={concert.sys.id}> <h3>{concert.titre}</h3> <p>日期:{new Date(concert.date).toLocaleString()}</p> </li> ))} </ul> <h2>已结束的演出</h2> <ul> {pastConcerts.map(concert => ( <li key={concert.sys.id}> <h3>{concert.titre}</h3> <p>日期:{new Date(concert.date).toLocaleString()}</p> </li> ))} </ul> </div> );
5. 优化建议
如果不需要实时刷新日期,可以移除每秒更新的定时器,初始化时获取一次客户端日期即可,减少不必要的重渲染。
内容的提问来源于stack exchange,提问作者ElTonyto
相关产品推荐
相关产品推荐

