反应路由器导航多页和反应滚动
React router navigation multipage and with react scroll
我正在尝试的是一个多页面反应应用程序,我可以在页面之间导航(比如从主要路线'/'到'/whitepape'或'privacyPolicy'),但我有4条不同的路线('/', 'services', 'features', 'contactUs') 在主路由 '/' 中,它使用 react-scroll 来获得在 Navbar 中添加链接的这 4 个组件之间的滚动(这部分按预期工作)。
但是在页面之间导航,比如用白皮书页面或隐私策略页面完全替换所有 4 个组件,导航栏和页脚在同一个地方,这样我就可以导航回家。
这就是我遇到的困难,感谢任何帮助我不确定我是否按照正确的方式来实现我需要的东西。我一直在 react native 中使用 React Navigation,它简单易懂且直接,希望 react-router 如此直接而不是 react-router 有点令人困惑。
App.js
function App() {
return (
<div className="App">
<Navbar />
<Switch>
<Route path="/">
<>
<Hero />
<Services />
<Features />
<ContactUs />
</>
</Route>
<Route path="/whitepaper">
<WhitePaper />
</Route>
</Switch>
<Footer />
</div>
)
}
Navbar.js
import { Link } from 'react-scroll'
import { withRouter, Link as RouterLink } from 'react-router-dom'
const menuItems = [
{
menuTitle: 'Home',
pageURL: '/',
id: 'hero'
},
{
menuTitle: 'Services',
pageURL: '/services',
id: 'services'
},
{
menuTitle: 'Features',
pageURL: '/features',
id: 'features'
},
{
menuTitle: 'Contact Us',
pageURL: '/contactUs',
id: 'contactUs'
}
]
const Navbar = ({ history }) => {
const classes = useStyles()
const [anchorEl, setAnchorEl] = useState(null)
const [showNav, setShowNav] = useState(false)
const open = Boolean(anchorEl)
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.down('sm'))
const [isActive, setIsActive] = useState('/')
useEffect(() => {
setIsActive(history.location.pathname)
window.addEventListener('scroll', () => {
if (window.scrollY > 100) {
setShowNav(true)
} else {
setShowNav(false)
}
})
return () => {
window.removeEventListener('scroll', () => setShowNav(false))
}
})
const handleMenu = event => {
setAnchorEl(event.currentTarget)
}
const handleMenuClick = pageURL => {
history.push(pageURL)
setAnchorEl(null)
}
const handleClose = () => {
setAnchorEl(null)
}
const handleLinkClick = pageURL => {
history.push(pageURL)
}
return (
<div>
<AppBar
position="static"
elevation={0}
className={`${classes.appBar} ${
showNav ? classes.appBarOnScroll : classes.appBar
}`}>
<Container>
<Toolbar className={classes.toolbar}>
<Link to="hero" smooth duration={1000}>
<RouterLink to="/">
<img src={logo} alt="Company Logo" className={classes.logo} />
</RouterLink>
</Link>
{isMobile ? (
<div>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
onClick={handleMenu}
aria-label="menu">
<MenuIcon />
</IconButton>
<Menu
className={classes.mobileMenu}
id="menu-appbar"
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right'
}}
open={open}
onClose={handleClose}>
{menuItems.map(menuItem => {
const { menuTitle, pageURL, id } = menuItem
return (
<Link key={menuTitle} to={id} smooth duration={1000}>
<MenuItem
className={
isActive === pageURL
? classes.mobileActiveMenuItem
: classes.mobileMenuItem
}
onClick={() => handleMenuClick(pageURL)}>
{menuTitle}
</MenuItem>
</Link>
)
})}
</Menu>
</div>
) : (
<div className={classes.menu}>
<Link
to="home"
smooth
duration={1000}
className={
isActive === '/' ? classes.menuActiveLink : classes.menuLink
}
variant="contained"
onClick={() => handleLinkClick('/')}>
Home
</Link>
<Link
to="services"
smooth
duration={1000}
className={
isActive === '/services'
? classes.menuActiveLink
: classes.menuLink
}
variant="contained"
onClick={() => handleLinkClick('/services')}>
Services
</Link>
<Link
to="features"
smooth
duration={1000}
className={
isActive === '/features'
? classes.menuActiveLink
: classes.menuLink
}
variant="contained"
onClick={() => handleLinkClick('/features')}>
Features
</Link>
<Link
to="contactUs"
smooth
duration={1000}
className={
isActive === '/contactUs'
? classes.menuActiveLink
: classes.menuLink
}
variant="contained"
onClick={() => handleLinkClick('/contactUs')}>
ContactUs
</Link>
</div>
)}
</Toolbar>
</Container>
</AppBar>
</div>
)
}
export default withRouter(Navbar)
Footer.js
import { Link } from 'react-scroll'
import { Link as RouterLink } from 'react-router-dom'
const Footer = () => {
const classes = useStyles()
const icons = [
{
img: linkedin,
alt: 'linkedin',
url: 'https://www.linkedin.com/company/company'
},
{
img: twitter,
alt: 'twitter',
url: 'https://twitter.com/company'
},
{
img: instagram,
alt: 'instagram',
url: 'https://www.instagram.com/company/'
},
{
img: facebook,
alt: 'facebook',
url: 'https://www.facebook.com/company/'
}
]
return (
<div className={classes.footer}>
<Container className={classes.container}>
<Grid container spacing={4}>
<Grid item md={3} xs={12}>
<div className={classes.column}>
<Link to="hero" smooth duration={1000}>
<RouterLink to="/">
<img className={classes.logo} src={logo} alt="Company Logo" />
</RouterLink>
</Link>
</div>
</Grid>
<Grid item md={3} xs={12}>
<div className={classes.column}>
<div>
<Grid item>
<span className={classes.linksTitle}>USEFUL LINKS</span>
</Grid>
<Grid item className={classes.links}>
<RouterLink to="/whitepaper" replace className={classes.link}>
<span className={classes.span}>White Paper</span>
</RouterLink>
</Grid>
<Grid item className={classes.links}>
<a
href="mailto:xyz@comapmy.com"
className={classes.link}>
<span className={classes.span}>Email Our CEO</span>
</a>
</Grid>
<Grid item className={classes.links}>
<RouterLink to="/" className={classes.link}>
<span className={classes.span}>Privacy Policy</span>
</RouterLink>
</Grid>
</div>
</div>
</Grid>
<Grid item md={3} xs={12}>
<div className={classes.column}>
{icons.map(icon => {
return (
<a href={icon.url} key={icon.alt}>
<img
className={classes.icon}
src={icon.img}
alt={icon.alt}
/>
</a>
)
})}
</div>
</Grid>
<Grid item md={3} xs={12}>
<div className={classes.top}>
<Link to="hero" smooth duration={1000}>
<RouterLink to="/">
<div>
<img src={top} alt="back to top" />
<p>Back To Top</p>
</div>
</RouterLink>
</Link>
</div>
</Grid>
</Grid>
<Grid container>
<Grid item xs={12}>
<div className={classes.footerBottom}>
<p className={classes.copyright}>
© 2021 Copyrights •{' '}
<Link to="hero" smooth duration={1000}>
<RouterLink to="/" className={classes.company}>
<span>company.com</span>
</RouterLink>
</Link>
</p>
</div>
</Grid>
</Grid>
</Container>
</div>
)
}
export default Footer
在 Switch
中,组件路径顺序和特异性很重要。不过,这并不是他们的文档中公开提到的细节。您想要在 较不具体的路径之前订购更具体的路径。将 path
视为更多的前缀,您会看到“/”是 all 路径的路径前缀。
Switch
returns 并呈现它在其子项中找到的第一个匹配路径。
只需颠倒路径的顺序,使 "/whitepaper"
列在更 general/less 具体的 "/"
路径之前。
function App() {
return (
<div className="App">
<Navbar />
<Switch>
<Route path="/whitepaper">
<WhitePaper />
</Route>
<Route path="/">
<>
<Hero />
<Services />
<Features />
<ContactUs />
</>
</Route>
</Switch>
<Footer />
</div>
)
}
我正在尝试的是一个多页面反应应用程序,我可以在页面之间导航(比如从主要路线'/'到'/whitepape'或'privacyPolicy'),但我有4条不同的路线('/', 'services', 'features', 'contactUs') 在主路由 '/' 中,它使用 react-scroll 来获得在 Navbar 中添加链接的这 4 个组件之间的滚动(这部分按预期工作)。
但是在页面之间导航,比如用白皮书页面或隐私策略页面完全替换所有 4 个组件,导航栏和页脚在同一个地方,这样我就可以导航回家。
这就是我遇到的困难,感谢任何帮助我不确定我是否按照正确的方式来实现我需要的东西。我一直在 react native 中使用 React Navigation,它简单易懂且直接,希望 react-router 如此直接而不是 react-router 有点令人困惑。
App.js
function App() {
return (
<div className="App">
<Navbar />
<Switch>
<Route path="/">
<>
<Hero />
<Services />
<Features />
<ContactUs />
</>
</Route>
<Route path="/whitepaper">
<WhitePaper />
</Route>
</Switch>
<Footer />
</div>
)
}
Navbar.js
import { Link } from 'react-scroll'
import { withRouter, Link as RouterLink } from 'react-router-dom'
const menuItems = [
{
menuTitle: 'Home',
pageURL: '/',
id: 'hero'
},
{
menuTitle: 'Services',
pageURL: '/services',
id: 'services'
},
{
menuTitle: 'Features',
pageURL: '/features',
id: 'features'
},
{
menuTitle: 'Contact Us',
pageURL: '/contactUs',
id: 'contactUs'
}
]
const Navbar = ({ history }) => {
const classes = useStyles()
const [anchorEl, setAnchorEl] = useState(null)
const [showNav, setShowNav] = useState(false)
const open = Boolean(anchorEl)
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.down('sm'))
const [isActive, setIsActive] = useState('/')
useEffect(() => {
setIsActive(history.location.pathname)
window.addEventListener('scroll', () => {
if (window.scrollY > 100) {
setShowNav(true)
} else {
setShowNav(false)
}
})
return () => {
window.removeEventListener('scroll', () => setShowNav(false))
}
})
const handleMenu = event => {
setAnchorEl(event.currentTarget)
}
const handleMenuClick = pageURL => {
history.push(pageURL)
setAnchorEl(null)
}
const handleClose = () => {
setAnchorEl(null)
}
const handleLinkClick = pageURL => {
history.push(pageURL)
}
return (
<div>
<AppBar
position="static"
elevation={0}
className={`${classes.appBar} ${
showNav ? classes.appBarOnScroll : classes.appBar
}`}>
<Container>
<Toolbar className={classes.toolbar}>
<Link to="hero" smooth duration={1000}>
<RouterLink to="/">
<img src={logo} alt="Company Logo" className={classes.logo} />
</RouterLink>
</Link>
{isMobile ? (
<div>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
onClick={handleMenu}
aria-label="menu">
<MenuIcon />
</IconButton>
<Menu
className={classes.mobileMenu}
id="menu-appbar"
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right'
}}
open={open}
onClose={handleClose}>
{menuItems.map(menuItem => {
const { menuTitle, pageURL, id } = menuItem
return (
<Link key={menuTitle} to={id} smooth duration={1000}>
<MenuItem
className={
isActive === pageURL
? classes.mobileActiveMenuItem
: classes.mobileMenuItem
}
onClick={() => handleMenuClick(pageURL)}>
{menuTitle}
</MenuItem>
</Link>
)
})}
</Menu>
</div>
) : (
<div className={classes.menu}>
<Link
to="home"
smooth
duration={1000}
className={
isActive === '/' ? classes.menuActiveLink : classes.menuLink
}
variant="contained"
onClick={() => handleLinkClick('/')}>
Home
</Link>
<Link
to="services"
smooth
duration={1000}
className={
isActive === '/services'
? classes.menuActiveLink
: classes.menuLink
}
variant="contained"
onClick={() => handleLinkClick('/services')}>
Services
</Link>
<Link
to="features"
smooth
duration={1000}
className={
isActive === '/features'
? classes.menuActiveLink
: classes.menuLink
}
variant="contained"
onClick={() => handleLinkClick('/features')}>
Features
</Link>
<Link
to="contactUs"
smooth
duration={1000}
className={
isActive === '/contactUs'
? classes.menuActiveLink
: classes.menuLink
}
variant="contained"
onClick={() => handleLinkClick('/contactUs')}>
ContactUs
</Link>
</div>
)}
</Toolbar>
</Container>
</AppBar>
</div>
)
}
export default withRouter(Navbar)
Footer.js
import { Link } from 'react-scroll'
import { Link as RouterLink } from 'react-router-dom'
const Footer = () => {
const classes = useStyles()
const icons = [
{
img: linkedin,
alt: 'linkedin',
url: 'https://www.linkedin.com/company/company'
},
{
img: twitter,
alt: 'twitter',
url: 'https://twitter.com/company'
},
{
img: instagram,
alt: 'instagram',
url: 'https://www.instagram.com/company/'
},
{
img: facebook,
alt: 'facebook',
url: 'https://www.facebook.com/company/'
}
]
return (
<div className={classes.footer}>
<Container className={classes.container}>
<Grid container spacing={4}>
<Grid item md={3} xs={12}>
<div className={classes.column}>
<Link to="hero" smooth duration={1000}>
<RouterLink to="/">
<img className={classes.logo} src={logo} alt="Company Logo" />
</RouterLink>
</Link>
</div>
</Grid>
<Grid item md={3} xs={12}>
<div className={classes.column}>
<div>
<Grid item>
<span className={classes.linksTitle}>USEFUL LINKS</span>
</Grid>
<Grid item className={classes.links}>
<RouterLink to="/whitepaper" replace className={classes.link}>
<span className={classes.span}>White Paper</span>
</RouterLink>
</Grid>
<Grid item className={classes.links}>
<a
href="mailto:xyz@comapmy.com"
className={classes.link}>
<span className={classes.span}>Email Our CEO</span>
</a>
</Grid>
<Grid item className={classes.links}>
<RouterLink to="/" className={classes.link}>
<span className={classes.span}>Privacy Policy</span>
</RouterLink>
</Grid>
</div>
</div>
</Grid>
<Grid item md={3} xs={12}>
<div className={classes.column}>
{icons.map(icon => {
return (
<a href={icon.url} key={icon.alt}>
<img
className={classes.icon}
src={icon.img}
alt={icon.alt}
/>
</a>
)
})}
</div>
</Grid>
<Grid item md={3} xs={12}>
<div className={classes.top}>
<Link to="hero" smooth duration={1000}>
<RouterLink to="/">
<div>
<img src={top} alt="back to top" />
<p>Back To Top</p>
</div>
</RouterLink>
</Link>
</div>
</Grid>
</Grid>
<Grid container>
<Grid item xs={12}>
<div className={classes.footerBottom}>
<p className={classes.copyright}>
© 2021 Copyrights •{' '}
<Link to="hero" smooth duration={1000}>
<RouterLink to="/" className={classes.company}>
<span>company.com</span>
</RouterLink>
</Link>
</p>
</div>
</Grid>
</Grid>
</Container>
</div>
)
}
export default Footer
在 Switch
中,组件路径顺序和特异性很重要。不过,这并不是他们的文档中公开提到的细节。您想要在 较不具体的路径之前订购更具体的路径。将 path
视为更多的前缀,您会看到“/”是 all 路径的路径前缀。
Switch
returns 并呈现它在其子项中找到的第一个匹配路径。
只需颠倒路径的顺序,使 "/whitepaper"
列在更 general/less 具体的 "/"
路径之前。
function App() {
return (
<div className="App">
<Navbar />
<Switch>
<Route path="/whitepaper">
<WhitePaper />
</Route>
<Route path="/">
<>
<Hero />
<Services />
<Features />
<ContactUs />
</>
</Route>
</Switch>
<Footer />
</div>
)
}