我仍在学习 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!');
}
从事件处理程序返回 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;