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

如何在Next.js+Supabase条目列表中集成更新状态表单?

如何将更新表单集成到数据库条目列表中?

核心问题梳理

你的代码目前有三个关键缺口:

  • 列表组件导入表单的方式错误
  • 表单提交时没有传递要更新的条目ID,服务端不知道操作哪条数据
  • 缺少表单展开/收起的交互逻辑(默认全展开体验不好)

下面是分步解决方法:


第一步:修正列表组件的表单集成

  1. 先修正表单的导入语句(你的表单是默认导出,不是命名导出):
// 替换原来的错误导入
import UpdatePublicationStatus from './updatePublicationStatusForm';
  1. 在列表组件中添加状态控制当前编辑的条目ID,实现点击编辑按钮展开对应表单:
export default function PendingPublicationList() {
    const [feeds, setFeeds] = useState<FeedType[]>([]);
    // 添加状态存当前编辑的feed ID,初始为null
    const [editingId, setEditingId] = useState<number | null>(null);
    
    // ... 原有fetch逻辑不变

    return (
        <div className="w-full">
            <p className="text-lg text-dark pb-4 font-baron">awaiting publication</p>  

            {feeds.map(pp => (
                <div key={pp.id} className="pt-2 border-b pb-4">
                    <div className="flex justify-between items-center">
                        <div className="capitalize text-sm text-dark font-baron">
                            {pp.title} 
                            <span className="text-tip font-sans text-sm ml-2"> 
                                {dayjs(pp.created_at).format('DD MMMM YYYY')}
                            </span>
                        </div>
                        {/* 添加编辑按钮,点击切换编辑状态 */}
                        <button 
                            onClick={() => setEditingId(prev => prev === pp.id ? null : pp.id)}
                            className="text-sm text-blue-600 hover:underline"
                        >
                            {editingId === pp.id ? '取消' : '编辑'}
                        </button>
                    </div>
                    
                    {/* 只渲染当前编辑条目的表单 */}
                    {editingId === pp.id && (
                        <UpdatePublicationStatus 
                            feed={pp as Database['public']['Tables']['feeds']['Row']} 
                            // 可选:传递回调,更新后刷新列表或关闭表单
                            onSuccess={() => {
                                setEditingId(null);
                                fetchPendingPublications();
                            }}
                        />
                    )}
                </div>
            ))}
        </div>
    );
}

第二步:修改表单组件,传递条目ID并优化初始值

  1. 在表单中添加隐藏的ID字段,让服务端知道要更新哪条数据
  2. 初始化发布日期为条目的现有值(如果有的话):
export default function UpdatePublicationStatus({ feed, onSuccess }: { feed: Database['public']['Tables']['feeds']['Row']; onSuccess?: () => void; }) {
  const [isPublished, setIsPublished] = useState(feed.published || false);
  // 初始化发布日期为现有值,没有则用当前日期
  const [publicationDate, setPublicationDate] = useState(
    feed.publicationDate ? dayjs(feed.publicationDate).format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD')
  );
  
  // ... 原有逻辑不变

  const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget as HTMLFormElement);
    // 手动添加ID到formData
    formData.append('id', feed.id.toString());

    try {
      await updatePublicationStatus(formData);
      console.log("Feed updated successfully");
      // 触发成功回调,让父组件刷新列表或关闭表单
      onSuccess?.();
    } catch (error) {
      if (error && typeof error === 'object' && "message" in error) {
        console.error("Error from server action:", (error as {message: string}).message);
      }
    }
  };

  return (
    <div className="mt-2">
      <form onSubmit={handleFormSubmit}>
        {/* 隐藏的ID字段 */}
        <input type="hidden" name="id" value={feed.id} />
        
        <div className="mb-2">
          <label className="mr-2">Confirmed for publication</label>
          <input
            name="published"
            className="cursor-pointer"
            type="checkbox"
            checked={isPublished}
            onChange={() => setIsPublished(prev => !prev)}
          />
        </div>
        <div className="mb-2">
          <label className="mb-2 block">Publication date</label>
          <input 
            name="publicationDate"
            type="date"
            className="bg-lighter border-none"
            value={publicationDate}
            onChange={(e) => setPublicationDate(e.target.value)}
          />
        </div>
       
        <button type="submit" className="bg-linkStyle hover:bg-linkOnHover text-light my-4 py-2 px-4 rounded-none">Update publication status</button>
      </form>
    </div>
  );
}

第三步:修复服务端Action,根据ID更新指定条目

现在从formData里获取ID,然后精准更新对应条目:

"use server"
import { revalidatePath } from "next/cache";
import { cookies } from "next/headers";
import { createServerActionClient } from "@supabase/auth-helpers-nextjs";

export const updatePublicationStatus = async (formData: FormData) => {
    const id = formData.get("id");
    const publicationDate = String(formData.get("publicationDate"));
    const published = formData.has("published"); // checkbox选中时会有该字段,直接判断即可
  
    if (!id) throw new Error("Missing feed ID");

    const cookieStore = cookies();
    const supabase = createServerActionClient<Database>({ cookies: () => cookieStore });
    
    const { data: { user } } = await supabase.auth.getUser();
  
    if (!user) throw new Error("No user found");

    const { error } = await supabase
        .from("feeds")
        .update({ published, publicationDate })
        .eq("id", id); // 关键:添加ID筛选,只更新指定条目

    if (error) throw new Error(error.message);
    
    revalidatePath("/");
}

额外优化点

  • 可以给表单添加加载状态,避免重复提交
  • 错误提示可以显示在页面上,而不是只在控制台输出
  • 列表刷新可以用Supabase的实时订阅替代手动调用fetchPendingPublications

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:55:04