Typescript 页面路由在单击时不会呈现子页面(React Router v6)

问题描述 投票:0回答:1

我仍在学习 Typescript,如果这看起来很简单,请道歉。

我在登陆页面上有一个应用程序 (App.tsx)。输入电子邮件并单击“让我们开始吧”按钮后,应该将电子邮件参数传播到“入门”页面并呈现 GetStarted 组件。现在,单击“让我们开始吧”按钮不会呈现任何新内容/路由到新页面。我在整个流程中记录了评论,但我注意到唯一记录的评论是在 App.tsx 中。这是我的逻辑:

当单击 App.tsx 中的“让我们开始吧”按钮时,会调用handleCreateProfileClick()。在此函数内,我调用该组件,并将用户输入的电子邮件作为参数。我有一个 AppRouter.tsx 文件,用于处理应用程序的所有路由(包括 GetStartedPage ofc)。不应在按钮单击渲染页面时调用 GetStartedPage,因为 AppRouter 链接差异。 slugs到每个页面?下面提供了代码,为了简洁省略了不重要的逻辑。

这是我的 App.tsx,其中有按钮:

import React, { useState, useEffect, useRef, ReactNode } from 'react';
import signinIcon from 'icons/signin_icon.png';
import './App.css';
import GetStartedPage from './GetStartedPage';
import SignInPage from './SignInPage';

const App = () : ReactNode => {
  const [showSidePanel, setShowSidePanel] = useState(false);
  const [email, setEmail] = useState('');

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

  const  handleCreateProfileClick = () => {
    const emailInput = document.getElementById('email-input') as HTMLInputElement;
    const email = emailInput.value;

    if (!email) {
      alert('Please enter your email');
      return;
    }
    console.log("About to navigate from handleCreateProfile in App.tsx");
    return <GetStartedPage inputEmail={email} />
  };

  const handleSignInClick = () => {
    return <SignInPage />
  };

  const handleResize = () => {
    if (window.innerWidth > 600) {
      setShowSidePanel(false); // Hide the side panel if the screen size is greater than 600px
    }
  };

  useEffect(() => {
    window.addEventListener('resize', handleResize); // Add event listener for window resize
    return () => {
      window.removeEventListener('resize', handleResize); // Remove event listener on component unmount
    };
  }, []); // Empty dependency array ensures that the effect runs only once on component mount

  
  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 href="/signin" onClick={handleSignInClick}>Sign in</a></u>.
      </div>
    </div>
    </div>
    </div>
    </div>
    );
};

export default App;

这是我的 AppRouter.tsx:

import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Routes, useNavigate, useLocation } from 'react-router-dom';
import App from './App';
import GetStartedPage from './GetStartedPage';

interface AppRouterProps {
  email: string;
}

const AppRouter: React.FC<AppRouterProps> = ({ email }) => {
  
  return (
    <Router>
      <Routes>
        <Route path="/" element={<App />} />
        <Route path="/create-profile" element={<GetStartedPage inputEmail={email} />} />
        <Route path="/sign-in" element={<SignInPage />} />
      </Routes>
    </Router>
  );
};

export default AppRouter;

这是我的 GetStarted.tsx 页面:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
interface GetStartedPageProps {
  inputEmail: string;
}

const GetStartedPage: React.FC<GetStartedPageProps> = (props) => {
  // More details here (omitted)
  console.log("Currently in Create profile page");
  // Updating the email state when the inputEmail prop changes, which we get from App.tsx
  useEffect(() => {
    setEmail(props.inputEmail);
  }, [props.inputEmail]);

    // More details here (omitted)
   
    try {
      await axios.post('/createProfile', userData);
      alert('Profile created successfully');
    } catch (error) {
      console.error('Error creating profile:', error);
      alert('Error creating profile');
    }
  };

  return (
    // More details here (omitted)
  );
};

export default GetStartedPage;

这是我的index.tsx:

import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './redux/store';
import App from '../../frontend/src/App';

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

  root.render(
    <Provider store={store}>
      {/* @ts-ignore */}
      <App>
      </App>
    </Provider>
  );
} else {
  console.error('Container element not found!');
}
reactjs typescript react-hooks react-router
1个回答
0
投票

从事件处理程序返回 JSX 并不是 React 组件渲染附加 UI 的方式。从代码和您的描述来看,您似乎应该 导航

"/create-profile"
"/sign-in"
路线来渲染
GetStartedPage
SignInPage
组件。

为此,您应该导入并使用

useNavigate
挂钩来访问
navigate
函数并向这些特定路线发出命令式导航操作。对于原始锚标记,您应该导入并渲染
Link
组件。

示例:

import { Link, useNavigate } from 'react-router-dom';

...

const App = () : ReactNode => {
  const navigate = useNavigate();

  const [showSidePanel, setShowSidePanel] = useState(false);
  const [email, setEmail] = useState('');

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

  const  handleCreateProfileClick = () => {
    const emailInput = document.getElementById('email-input') as HTMLInputElement;
    const email = emailInput.value;

    if (!email) {
      alert('Please enter your email');
      return;
    }
    
    return navigate("/create-profile"); // <-- navigate
  };

  const handleSignInClick = () => {
    return navigate("/sign-in"); // <-- navigate
  };

  ...

  
  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
                type="button"
                className="lets-go-button"
                onClick={handleCreateProfileClick}
              >
                Let's get started
              </button>
            </div>
            <div className="sign-in">
              Already joined? <Link to="/signin"><u>Sign in</u></a>.
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default App;
© www.soinside.com 2019 - 2024. All rights reserved.