React 18/Next.js 13跨页面传递useState状态的最佳实践
Next.js 13/React 18跨页面状态传递(删除提醒功能)最佳实践
针对你需要把/reminders页面的reminders和setReminders状态传递到/reminders/overview/[id]页面实现删除功能的需求,下面是几个落地性强的最佳实践方案:
方案1:React Context全局状态管理(推荐)
在Next.js 13 App Router中,通过父路由的Layout提供Context,让所有子路由页面/组件共享状态,这是跨路由组件传递状态的标准方案。
步骤1:创建Reminder Context
在/lib目录下新建ReminderContext.tsx:
"use client"; import React, { createContext, useContext, useState, ReactNode } from "react"; interface Reminder { id: string; content: string; } interface ReminderContextType { reminders: Reminder[]; setReminders: React.Dispatch<React.SetStateAction<Reminder[]>>; } const ReminderContext = createContext<ReminderContextType | undefined>(undefined); export function ReminderProvider({ children }: { children: ReactNode }) { const [reminders, setReminders] = useState<Reminder[]>([]); // 从测试数据初始化状态 React.useEffect(() => { import("@/lib/test_data").then((module) => { setReminders(module.default); }); }, []); return ( <ReminderContext.Provider value={{ reminders, setReminders }}> {children} </ReminderContext.Provider> ); } export function useReminders() { const context = useContext(ReminderContext); if (!context) { throw new Error("useReminders必须在ReminderProvider内部使用"); } return context; }
步骤2:在Reminders路由的Layout中注入Provider
在/app/reminders目录下新建layout.tsx:
"use client"; import { ReminderProvider } from "@/lib/ReminderContext"; export default function RemindersLayout({ children, }: { children: React.ReactNode; }) { return <ReminderProvider>{children}</ReminderProvider>; }
步骤3:修改RemindersPage使用Context
修改/app/reminders/page.tsx:
"use client"; import ReminderComponent from "@/lib/ReminderComponent"; import { useReminders } from "@/lib/ReminderContext"; import deleteReminder from "@/lib/deleteReminder"; export default function RemindersPage() { const { reminders } = useReminders(); return( <div> {reminders.map((reminder) => ( <ReminderComponent key={reminder.id} id={reminder.id} content={reminder.content} deleteReminder={deleteReminder} /> ))} </div> ) }
步骤4:简化ReminderComponent的Props
修改/lib/ReminderComponent.tsx:
"use client"; import React from "react"; import { useRouter } from "next/navigation"; import { useReminders } from "@/lib/ReminderContext"; interface ComponentProps { id: string; content: string; deleteReminder: (event: React.MouseEvent<HTMLButtonElement>, id: string) => void; } export default function ReminderComponent(props: ComponentProps) { const router = useRouter(); const { reminders, setReminders } = useReminders(); const navigateToOverview = () => router.push(`reminders/overview/${props.id}`); return( <div onClick={navigateToOverview} > <div>{props.content}</div> <button onClick={(e) => props.deleteReminder(e, props.id, reminders, setReminders)}> 删除提醒 </button> </div> ) }
步骤5:修改OverviewPage使用Context实现删除
修改/app/reminders/overview/[id]/page.tsx:
"use client"; import { useRouter } from "next/navigation"; import { useReminders } from "@/lib/ReminderContext"; import deleteReminder from "@/lib/deleteReminder"; interface PageProps { params: {id: string}; } export default function OverviewPage ({params}: PageProps) { const router = useRouter(); const { reminders, setReminders } = useReminders(); const navigateBack = () => router.back(); const reminder = reminders.find((element) => element.id === params.id); if (!reminder) { return <div>未找到该提醒</div>; } return ( <div> <div>{reminder.content}</div> <button onClick={(e) => { deleteReminder(e, params.id, reminders, setReminders); navigateBack(); }}> 删除 </button> </div> ) }
步骤6:修正deleteReminder的变量名错误
修改/lib/deleteReminder.ts:
import React from "react"; interface Reminder { id: string; content: string; } const deleteReminder = (event: React.MouseEvent<HTMLButtonElement>, id: string, reminders: Reminder[], setReminders: React.Dispatch<React.SetStateAction<Reminder[]>>) =>{ event.stopPropagation(); event.preventDefault(); const updatedReminders = reminders.filter((reminder) => reminder.id !== id); setReminders(updatedReminders); } export default deleteReminder;
方案2:使用客户端存储(localStorage)持久化状态
如果需要状态在页面刷新后依然保留,可以把reminders存在localStorage中,所有页面从localStorage读取和更新。
修改RemindersPage的状态逻辑:
import { useState, useEffect } from "react"; import TEST_DATA from "@/lib/test_data" export default function RemindersPage() { const [reminders, setReminders] = useState<Reminder[]>(() => { const saved = localStorage.getItem("reminders"); return saved ? JSON.parse(saved) : TEST_DATA; }); // 状态变化时同步到localStorage useEffect(() => { localStorage.setItem("reminders", JSON.stringify(reminders)); }, [reminders]); // 其他代码不变 }
修改OverviewPage的状态逻辑:
import { useState, useEffect } from "react"; import TEST_DATA from "@/lib/test_data" export default function OverviewPage ({params}: PageProps) { const [reminders, setReminders] = useState<Reminder[]>(() => { const saved = localStorage.getItem("reminders"); return saved ? JSON.parse(saved) : TEST_DATA; }); useEffect(() => { localStorage.setItem("reminders", JSON.stringify(reminders)); }, [reminders]); // 其他代码不变 }
这种方式不需要Context,直接在每个页面维护状态,但要注意多页面同步问题,适合简单的本地持久化场景。
方案3:URL参数传递+页面刷新(简易方案)
如果不想用全局状态,可以在删除后通过router.refresh()刷新列表页,前提是列表页的状态从外部数据源(如localStorage)获取,而非仅依赖初始useState。
修改OverviewPage的删除逻辑:
<button onClick={(e) => { e.stopPropagation(); e.preventDefault(); // 直接刷新页面,触发列表页重新读取数据源 router.refresh(); navigateBack(); }}> 删除 </button>
这种方式适合快速实现,但状态同步性较差,仅推荐用于极简场景。
内容的提问来源于stack exchange,提问作者MiK
相关产品推荐
相关产品推荐

