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

React中Link的onClick设置props在History组件中为undefined的问题

Let's break down why this is happening and walk through actionable fixes:

The Root Cause

React's useState updates are asynchronous. When you click the Link in your Item component, two actions fire almost simultaneously:

  1. You call setPropsPassword(password) to update the password state in the parent Store component.
  2. The Link triggers an immediate route change to /history/:id.

Since state updates don't take effect instantly, the History component mounts before the password state finishes updating. That's why it receives the initial undefined value as prePassword.

Your other working Link in the Item component probably doesn't trigger a cross-route navigation—so the component re-renders naturally after the state update completes, allowing it to pick up the new password value.

Fix Options

Option 1: Use useNavigate to Delay Navigation Until State Updates

Instead of relying on Link, use React Router's useNavigate hook to explicitly navigate only after the state update has a chance to apply. We'll use useEffect to listen for state changes:

  1. Update your Item component:
    import { useNavigate } from 'react-router-dom';
    import { useEffect, useState } from 'react';
    
    export function Item({ id, prePassword, updateList, setPropsPassword }) { 
      const navigate = useNavigate();
      const [shouldNavigate, setShouldNavigate] = useState(false);
    
      const handleOpenHistory = () => {
        setPropsPassword(password);
        setShouldNavigate(true);
      };
    
      // Navigate only once the password state has updated
      useEffect(() => {
        if (shouldNavigate) {
          navigate(`/history/${id}`);
          setShouldNavigate(false);
        }
      }, [shouldNavigate, navigate, id]);
    
      // Replace Link with a button (or keep Link and prevent default behavior)
      return (
        <button onClick={handleOpenHistory} className="btn-open-history float-left btn btn-primary">
          Geschiedenis
        </button>
      );
    }
    

Option 2: Pass Password as a Route Query Parameter

If the password isn't sensitive, attach it directly to the URL as a query parameter. This lets the History component retrieve it from the route, eliminating the need to rely on parent state:

  1. Update the Link in Item:

    <Link 
      to={`/history/${id}?password=${encodeURIComponent(password)}`} 
      className="btn-open-history float-left btn btn-primary"
    >
      Geschiedenis
    </Link>
    
  2. Modify your History component to read the query parameter. Since it's a class component, wrap it with withRouter to access the location prop:

    import { withRouter } from 'react-router-dom';
    
    class History extends React.Component { 
      componentDidMount() {
        const searchParams = new URLSearchParams(this.props.location.search);
        const password = searchParams.get('password');
        console.log('Password from route:', password);
        // You can store this in component state if needed
      }
    
      render() {
        return (...)
      }
    }
    
    export default withRouter(History);
    

Option 3: Guard History Render Until password is Available

In your parent Store component, add a check for password before rendering History. This ensures the component only mounts once the state has been updated:

{props.match.path=="/history/:id" && id && password && <History prePassword={password} id={id} key="item" />}

Note: This will prevent History from rendering if password is undefined, so only use this if that aligns with your business logic.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:07:35