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

BrowserRouter的Link覆盖onClick事件导致State Hook更新失败如何解决

问题根因

你遇到的问题有两个核心原因:

  • 你给自定义Card组件传入的onClick没有生效:如果Card组件内部没有将接收的onClick属性绑定到自身的根DOM节点上,外层传入的点击事件本身就不会触发。
  • 即使onClick能触发,setTask是React的异步状态更新,而Link的跳转行为会优先执行,跳转后Home组件直接卸载,状态更新逻辑还没执行就被中断了,同时Home组件内部的state是组件私有数据,也无法直接传递给跳转后的PlayerPage组件。

解决方案

不需要额外维护Home的state,直接用React Router自带的路由传参能力实现需求,修改代码如下:

修改后的Home.js代码

import { Link } from "react-router-dom";
import { useState, useEffect } from "react";

export default function Home() {
  return (
    <>
     <Header />
      <main className="home-main">
       <div className="main-wrap">
        <section className="card-container">
         <h1>Good Morning</h1>
           <h1>Choose Your Work Style</h1>

            <div className="card-wrap">
              {/* 把要传递的参数放在Link的state属性里,点击事件直接写在Link上更稳妥 */}
              <Link 
                to={{
                  pathname: "/PlayerPage",
                  state: { task: 'Short Task' }
                }}
                onClick={() => console.log('点击触发,将要传递的task值为:Short Task')}
              >
                  <Card
                    taskName="Short Task"
                    description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
                  />
              </Link>
            </div>
         </section>
        </div>
      </main>
   </>
 );
}

修改后的PlayerPage.js代码

import { useLocation } from "react-router-dom";
import Header from "../components/Header";
import Timer from "../components/Timer";
import "./PlayerPage.scss";

export default function PlayerPage() {
  // 用useLocation钩子接收路由传递的参数
  const location = useLocation();
  const task = location.state?.task;

  return (
    <>
      <Header />
      <main className="player-page-main">
        <div className="player-page-main-wrap">
          <div className="timer-title-wrap">
            <Timer />
            <h2 className="task-title">{task || '未选择任务'}</h2>
          </div>
        </div>
      </main>
    </>
  );
}

可选方案:必须先更新state再跳转的场景

如果你确实需要先执行Home的状态更新逻辑再跳转,可以不用Link组件,改用useNavigate钩子手动控制跳转时机:

import { useNavigate } from "react-router-dom";
import { useState, useEffect } from "react";

export default function Home() {
  const [task, setTask] = useState();
  const navigate = useNavigate();

  useEffect(() => {
    console.log(task);
    // 状态更新完成后再跳转
    if(task) {
      navigate('/PlayerPage', { state: { task } })
    }
  },[task, navigate])

  const handleCardClick = () => {
    setTask('Short Task')
  }

  return (
    <>
     <Header />
      <main className="home-main">
       <div className="main-wrap">
        <section className="card-container">
         <h1>Good Morning</h1>
           <h1>Choose Your Work Style</h1>

            <div className="card-wrap">
              {/* 注意要确保Card组件内部接收onClick并绑定到根DOM节点,点击事件才会生效 */}
                  <Card 
                    onClick={handleCardClick}
                    taskName="Short Task"
                    description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
                  />
            </div>
         </section>
        </div>
      </main>
   </>
 );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 05:00:01