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

React Router v6点击按钮无法渲染子页面(Typescript)

React路由跳转失败问题解决

我开发了一个基于TypeScript的React应用,首页是App.tsx。用户输入邮箱后点击“Let's get started”按钮,预期要把邮箱参数传给GetStartedPage组件并渲染该页面,但点击按钮后没有任何跳转或页面渲染,只有App.tsx里的日志能输出。

我的错误逻辑是:点击按钮时调用handleCreateProfileClick()函数,在函数里直接返回<GetStartedPage inputEmail={email} />组件。虽然已经在AppRouter.tsx里配置了包含GetStartedPage的路由规则,但不知道为什么直接返回组件无法触发页面渲染。


核心问题分析

React的点击事件处理器不能通过返回组件来触发页面渲染/跳转,事件处理器的返回值会被忽略。要实现页面跳转,必须使用react-router-dom提供的导航API。另外入口文件没有正确使用路由配置,导致路由规则根本没生效。

分步修复方案

1. 修复入口文件index.tsx

当前入口直接渲染App组件,没有使用AppRouter,导致路由配置完全没生效。修改为渲染AppRouter:

import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './redux/store';
import AppRouter from './AppRouter'; // 导入AppRouter

const container = document.getElementById('root');
if (container) {
  const root = createRoot(container);

  root.render(
    <Provider store={store}>
      <AppRouter />
    </Provider>
  );
} else {
  console.error('Container element not found!');
}

2. 修改App.tsx,使用路由导航代替返回组件

在App组件中通过useNavigate钩子获取导航方法,点击按钮时调用navigate跳转,同时把邮箱参数通过路由状态传递:

import React, { useState, useEffect, ReactNode } from 'react';
import signinIcon from 'icons/signin_icon.png';
import './App.css';
import { useNavigate } from 'react-router-dom'; // 导入useNavigate

const App = () : ReactNode => {
  const [showSidePanel, setShowSidePanel] = useState(false);
  const [email, setEmail] = useState('');
  const navigate = useNavigate(); // 获取导航函数

  const handleEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setEmail(event.target.value);
  };

  const handleCreateProfileClick = () => {
    if (!email) {
      alert('Please enter your email');
      return;
    }
    console.log("About to navigate from handleCreateProfile in App.tsx");
    // 跳转到/create-profile路由,把邮箱放在state里
    navigate('/create-profile', { state: { email } });
  };

  const handleSignInClick = () => {
    // 同样用navigate跳转,不要返回组件
    navigate('/sign-in');
  };

  const handleResize = () => {
    if (window.innerWidth > 600) {
      setShowSidePanel(false);
    }
  };

  useEffect(() => {
    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  return (
    <div className="App">
      <div id="page-container">
        <div className="menu">
          <div className="menu-item sign-up" onClick={handleSignInClick}>
            <img src={signinIcon} alt="Sign in" className="signin"/>
            <span className="sign-up-text">Sign in</span>
          </div>
        </div>
        <div className="container">
          <div className="left-content">
            <div className="email-form">
              <input
                type="email"
                placeholder="Email address"
                onChange={handleEmailChange}
                value={email}
                id="email-input"
                required
              />
              <button className="lets-go-button" onClick={handleCreateProfileClick}>
                Let's get started
              </button>
            </div>
            <div className="sign-in">
              Already joined? 
              <u>
                {/* 阻止a标签默认跳转,用onClick处理 */}
                <a href="/signin" onClick={(e) => {
                  e.preventDefault();
                  handleSignInClick();
                }}>Sign in</a>
              </u>.
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default App;

3. 修正AppRouter.tsx的路由配置

不需要给AppRouter传递email参数,邮箱参数通过路由状态传递,GetStartedPage直接从路由状态中获取:

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import App from './App';
import GetStartedPage from './GetStartedPage';
import SignInPage from './SignInPage'; // 导入SignInPage

const AppRouter = () => {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<App />} />
        <Route path="/create-profile" element={<GetStartedPage />} />
        <Route path="/sign-in" element={<SignInPage />} />
      </Routes>
    </Router>
  );
};

export default AppRouter;

4. 修改GetStartedPage.tsx获取路由状态中的邮箱

使用useLocation钩子获取路由状态里的邮箱:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useLocation } from 'react-router-dom'; // 导入useLocation

const GetStartedPage = () => {
  const [email, setEmail] = useState('');
  const location = useLocation(); // 获取路由位置对象

  useEffect(() => {
    // 从路由state中取出邮箱
    if (location.state?.email) {
      setEmail(location.state.email);
    }
  }, [location.state]);

  console.log("Currently in Create profile page");

  // 修正async函数包裹await逻辑
  const createProfile = async () => {
    try {
      await axios.post('/createProfile', { email /* 其他用户数据 */ });
      alert('Profile created successfully');
    } catch (error) {
      console.error('Error creating profile:', error);
      alert('Error creating profile');
    }
  };

  return (
    <div>
      <h1>Get Started</h1>
      <p>Email: {email}</p>
      {/* 其他页面元素 */}
    </div>
  );
};

export default GetStartedPage;

关键知识点总结

  • React事件处理器的返回值不会影响组件渲染,必须通过状态更新或路由导航来改变页面内容。
  • 使用react-router-dom的useNavigate实现路由跳转,useLocation获取路由状态参数。
  • 入口文件必须渲染包含路由配置的组件,否则路由规则不会生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:48:12