[英]Why do I have to manually refresh the page for the component to load when using react-router?
I have a React application that uses react-router-dom to load different components from the sidebar.
我有一个 React 应用程序,它使用 react-router-dom 从侧边栏加载不同的组件。 Whenever I click the link in the sidebar, the URL changes, but I must manually refresh the page to get the actual content of the page to load.
每当我单击侧边栏中的链接时,URL 都会发生变化,但我必须手动刷新页面以获取要加载的页面的实际内容。
I want my application to automatically refresh the page when a sidebar link is clicked instead of the user having to manually refresh the page in order for a component to load.我希望我的应用程序在单击侧边栏链接时自动刷新页面,而不是用户必须手动刷新页面才能加载组件。
function App() {
const [locale, setLocale] = useState('en');
return (
<>
<Routes>
<Route path="/" element={<IntlProvider locale={locale}><Layout setLocale={setLocale} /></IntlProvider>}>
<Route index element={<Home />} />
<Route path="experience" element={<Experience />} />
<Route path="skills" element={<Skills />} />
<Route path="portfolio" element={<Portfolio />} />
<Route path="contact" element={<Contact />} />
</Route>
</Routes>
</>
);
}
export default App;
This is my App.js这是我的 App.js
const Sidebar = ({ toggled, handleToggleSidebar }) => {
const intl = useIntl();
return (
<ProSidebar
toggled={toggled}
breakPoint="md"
onToggle={handleToggleSidebar}
>
<SidebarHeader>
<div
style={{
padding: '24px',
textTransform: 'uppercase',
fontWeight: 'bold',
fontSize: 14,
letterSpacing: '1px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
<Link style={{ display: 'block', padding: '15px 0' }} to="/">
<img style={{ display: 'block', margin: '-3em 3em', width: '133px', height: 'auto' }} src={LogoS} alt="Logo" />
</Link>
</div>
</SidebarHeader>
<SidebarContent>
<Menu iconShape="circle">
<MenuItem icon={<FaHome size={32} />}>
{intl.formatMessage({ id: 'Home' })}
<NavLink activeclassname="active" to="/"></NavLink>
</MenuItem>
<MenuItem icon={<FaProjectDiagram size={32} />}>
{intl.formatMessage({ id: 'Experience' })}
<NavLink to="/experience"></NavLink>
</MenuItem>
<MenuItem icon={<FaToolbox size={32} />}>
{intl.formatMessage({ id: 'Skills' })}
<NavLink to="/skills"></NavLink>
</MenuItem>
<MenuItem icon={<FaFolderOpen size={32} />}>
{intl.formatMessage({ id: 'Portfolio' })}
<NavLink to="/portfolio"></NavLink>
</MenuItem>
<MenuItem icon={<FaTelegramPlane size={32} />}>
{intl.formatMessage({ id: 'Contact' })}
<NavLink to="/contact"></NavLink>
</MenuItem>
</Menu>
</SidebarContent>
</ProSidebar >
);
};
export default Sidebar;
This is my Sidebar.js这是我的 Sidebar.js
function Layout({ setLocale }) {
const [rtl, setRtl] = useState(false);
const [collapsed, setCollapsed] = useState(false);
const [image, setImage] = useState(true);
const [toggled, setToggled] = useState(false);
const handleCollapsedChange = (checked) => {
setCollapsed(checked);
};
const handleRtlChange = (checked) => {
setRtl(checked);
setLocale(checked ? 'ar' : 'en');
};
const handleImageChange = (checked) => {
setImage(checked);
};
const handleToggleSidebar = (value) => {
setToggled(value);
};
return (
<div className={`app ${rtl ? 'rtl' : ''} ${toggled ? 'toggled' : ''}`}>
<Sidebar
image={image}
collapsed={collapsed}
rtl={rtl}
toggled={toggled}
handleToggleSidebar={handleToggleSidebar}
/>
<Main
image={image}
toggled={toggled}
collapsed={collapsed}
rtl={rtl}
handleToggleSidebar={handleToggleSidebar}
handleCollapsedChange={handleCollapsedChange}
handleRtlChange={handleRtlChange}
handleImageChange={handleImageChange}
/>
<Outlet />
</div>
);
}
export default Layout;
This is the Layout.js that renders the page.这是呈现页面的 Layout.js。
const Contact = () => {
const [letterClass, setLetterClass] = useState('text-animate')
const form = useRef()
useEffect(() => {
return setTimeout(() => {
setLetterClass('text-animate-hover')
}, 3000)
}, [])
const sendEmail = (e) => {
e.preventDefault()
emailjs
.sendForm(
'service_v8uv1al',
'template_xge6tgj',
form.current,
'UuX3z3S-mWAnAL7BY')
.then(
() => {
alert('Message successfully sent!')
window.location.reload(false)
},
() => {
alert('Failed to send the message, please try again')
}
)
}
return (
<>
<div className="container contact-page">
<div className="text-zone">
<h1>
<AnimatedLetters
letterClass={letterClass}
strArray={['C', 'o', 'n', 't', 'a', 'c', 't', ' ', 'm', 'e']}
idx={15}
/>
</h1>
<div className='app_footer-cards'>
<div className='app_footer-card'>
<img src={emailLogo} alt="email" />
<a href="mailto:k.maumau11@gmail.com" className='p-text'>k.maumau0@gmail.com</a>
</div>
<div className='app_footer-card'>
<img src={phoneLogo} alt="mobile" />
<a href="tel: +1 (832) 764-9796" className='p-text'>+1 (832) 764-9796</a>
</div>
</div>
<p>
If you have a request or question, or simply just want to
say Hello don't hesitate to contact me using the form below!
</p>
<div className="contact-form">
<form ref={form} onSubmit={sendEmail}>
<ul>
<li className="half">
<input placeholder="Name" type="text" name="name" required />
</li>
<li className="half">
<input
placeholder="Email"
type="email"
name="email"
required
/>
</li>
<li>
<input
placeholder="Subject"
type="text"
name="subject"
required
/>
</li>
<li>
<textarea
placeholder="Message"
name="message"
required
></textarea>
</li>
<li>
<input type="submit" className="flat-button" value="SEND" />
</li>
</ul>
</form>
</div>
</div>
</div>
<Loader type="ball-scale" />
</>
)
}
export default Contact
Contact Page Code联系页面代码
Your app code is actually crashing when navigating away from a page.离开页面时,您的应用程序代码实际上正在崩溃。 It's not clear why you aren't seeing the React error page ( perhaps you are running a production build ) but the issue is that for each page you are using a
useEffect
hook to set a timeout to update some local state.目前尚不清楚为什么您没有看到 React 错误页面(也许您正在运行生产构建),但问题是对于每个页面,您都使用
useEffect
挂钩来设置超时以更新某些本地状态。
useEffect(() => {
return setTimeout(() => {
setLetterClass('text-animate-hover');
}, 3000);
}, []);
The issue with this is that React assumes that anything returned from the useEffect
hook is a cleanup function to be invoked when the component is rerendering/unmounting.问题在于 React 假定从
useEffect
挂钩返回的任何内容都是在组件重新渲染/卸载时调用的清理函数。 setTimeout
returns a number representing the timer id. setTimeout
返回一个表示计时器 ID 的数字。
Reloading the page is effectively reloading the entire app on the current URL path.重新加载页面实际上是在当前 URL 路径上重新加载整个应用程序。
On each of these pages, refactor the logic to return a cleanup function that clears the timeout.在每个页面上,重构逻辑以返回清除超时的清理函数。
useEffect(() => {
const timer = setTimeout(() => {
setLetterClass('text-animate-hover');
}, 3000);
return () => clearTimeout(timer);
}, []);
This allows the timeout to be instantiated when the component mounts, and for the offhand chance the user navigates away from the page and this component unmounts, it will clear the timeout and won't invoke the callback that will enqueue a state state.这允许在组件安装时实例化超时,并且对于用户导航离开页面并且该组件卸载的偶然机会,它将清除超时并且不会调用将使状态状态排队的回调。
It seems that each of these pages has the same animation letterClass
state for the AnimatedLetters
component.对于
AnimatedLetters
组件,这些页面中的每一个似乎都具有相同的动画letterClass
状态。 Instead of duplicating the same code/logic across all pages, abstract it into a custom React hook that returns the letterClass
value.与其在所有页面上复制相同的代码/逻辑,不如将其抽象为一个自定义的 React 钩子,该钩子返回
letterClass
值。
Example:例子:
const useLetterClass = ({
start = 'text-animate',
end = 'text-animate-hover'
}) => {
const [letterClass, setLetterClass] = useState(start);
useEffect(() => {
const timer = setTimeout(() => {
setLetterClass(end);
}, 3000);
return () => clearTimeout(timer);
}, []);
return { letterClass };
};
In each page component import the useLetterClass
hook, call, and pass the returned letterClass
prop value.在每个页面组件中导入
useLetterClass
挂钩,调用并传递返回的letterClass
值。
Example:例子:
const Contact = () => {
const { letterClass } = useLetterClass({
start: 'text-animate',
end: 'text-animate-hover',
});
const form = useRef();
const sendEmail = (e) => {
...
}
return (
<>
<div className="container contact-page">
<div className="text-zone">
<h1>
<AnimatedLetters
letterClass={letterClass}
strArray={['C', 'o', 'n', 't', 'a', 'c', 't', ' ', 'm', 'e']}
idx={15}
/>
</h1>
...
</div>
</div>
<Loader type="ball-scale" />
</>
);
};
The sandbox code you provided also seems to have an issue with some of the SCSS, specifically with a $sidebar-color
variable missing.您提供的沙箱代码似乎也有一些SCSS 的问题,特别是缺少
$sidebar-color
变量。 I'm not familiar with SCSS much, but I don't suspect it is related to the routing/navigation issue I described above.我对 SCSS 不太熟悉,但我不怀疑它与我上面描述的路由/导航问题有关。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.