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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 17:06:04