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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:27:56