react-router: unable to route to child components - javascript

i am building an online database using react and the routes have been set up such that if user is not authenticated, they will be redirected to the login page.
However, i am facing difficulties for the nested routes. i think some parts of the implementation is incorrect.
2 problems:
In order for the "404" (handled by NotFound component) page to work, exact props has to be used in <Route/>
However if exact props is used, the <Links/> found in FixedDrawer component will not work. Clicking any of them will direct to "404" page.
What am i doing wrong here?
For simplicity's sake, i will only be sharing the rendering parts of the components.
Code as below:
App.js (PageShell is only used for animating page transitions)
import LoginPage from "./pages/LoginPage";
import Dashboard from "./pages/Dashboard";
import NotFound from "./pages/NotFound";
.
.
.
render() {
const childProps = {
isAuthenticated: this.state.isAuthenticated,
userHasAuthenticated: this.userHasAuthenticated
};
return (
<div className="App">
<Switch>
<Route path="/login" exact component={PageShell(LoginPage)} />
<Route path="/" exact component={PageShell(Dashboard)} />
<Route component={NotFound} />
</Switch>
</div>
);
Dashboard.js
render() {
return (
<div>
<NavBar user={this.state.user} />
<FixedDrawer handleSetCategory={this.handleSetCategory} />
<Switch>
<Route path="/athletes" render={() => <AthletesDataTable />} />
<Route path="/races" render={() => <RacesDataTable />} />
</Switch>
</div>
);
}
FixedDrawer.js
class FixedDrawer extends Component {
constructor() {
super();
this.state = {};
}
render() {
return (
<Drawer variant="permanent" elevation={10}>
<List component="nav" style={{ top: 65 }}>
<ListItem button>
<ListItemIcon>
<FaceIcon />
</ListItemIcon>
<Link to="/athletes" style={{ textDecoration: "none" }}>
<ListItemText primary="Athletes" />
</Link>
</ListItem>
<ListItem button>
<ListItemIcon>
<GroupIcon />
</ListItemIcon>
<Link to="/teams" style={{ textDecoration: "none" }}>
<ListItemText primary="Teams" />
</Link>
</ListItem>
<ListItem button>
<ListItemIcon>
<DateRangeIcon />
</ListItemIcon>
<Link to="/meets" style={{ textDecoration: "none" }}>
<ListItemText primary="Meets" />
</Link>
</ListItem>
<ListItem button>
<ListItemIcon>
<PoolIcon />
</ListItemIcon>
<Link to="/races" style={{ textDecoration: "none" }}>
<ListItemText primary="Races" />
</Link>
</ListItem>
<ListItem button>
<ListItemIcon>
<AssignmentIcon />
</ListItemIcon>
<Link to="/results" style={{ textDecoration: "none" }}>
<ListItemText primary="Race Results" />
</Link>
</ListItem>
</List>
</Drawer>
);
}
}

"Link" component will try to match the exact route. Since, "/meets", "/teams" doesn't match the routes you provided, it will give 404 page.
return (
<div className="App">
<Navbar />
<Sidebar />
<Switch>
<Route path="/login" exact component={PageShell(LoginPage)} />
<Route path="/:val" component={PageShell(SomePage)} />
<Route path="/" exact component={PageShell(Dashboard)} />
<Route component={NotFound} />
</Switch>
<Footer />
</div>
);
I'll suggest you write the route component as above. And in the componentDidMount of "SomePage" component, you can get the value of "val" as mentioned in the path above in "this.props.match" object and render the "SomePage" component as per the routes you want.
Ex: In the didMount function of SomePage:
componentDidMount(){
this.setState({val: this.props.match.params.val})
}
render(){
return(
<div>
{
this.state.val === 'teams' ? <TeamsComponent /> : null
}
{
this.state.val === 'meets' ? <MeetsComponent /> : null
}
</div>
)
}

Related

After adding framer-motion, routing not works but link change

I added framer motion to my project, because i want to make some animations between pages, but now i've been staying all the time at the home page. I will be grateful for any help. Here's my code:
class App extends Component {
//(...)
location = () => {
useLocation();
}
//(...)
<Router>
<nav>
{!this.state.setIsAuth ? (
<>
<Link to="/">Home</Link>
<Link to="/contact">Contact</Link>
<Link to="/login"> Login </Link>
</>
) : (
<>
<Link to="/news"> News </Link>
<Link to="/createpost"> Create Post </Link>
<Link to="/calendar"> Calendar </Link>
<a href="/" onClick={this.signUserOut}> Log Out</a>
</>)}
</nav>
<AnimatePresence>
<Routes location={this.location} key={this.location.pathname}>
<Route exact path="/" element={<Home />} />
<Route path="/news" element={<News />} />
<Route path="/login" element={<Login setIsAuth={this.signIn} />} />
<Route path="/contact" element={<Contact />} />
<Route path="/createpost" element={<CreatePost setIsAuth={this.signIn} />} />
<Route path="/calendar" element={<Calendar />} />
</Routes>
</AnimatePresence>
</Router>
and Home.js to show you how structures of my pages look like
class Home extends Component {
render() {
return (
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
<header className="header">
<div className="header__text-box">
<h1 className="heading__text-box">
<span className="heading-primary--main">TeamWork</span>
<span className="heading-primary--sub">THE WAY TO SUCCESS</span>
</h1>
Take your opportunity
</div>
</header>
</motion.div>
)
}
}

React webpage refreshing every 4-6 seconds

I'm not really sure even what part of my code to show because it's such a general error, but everytime I npm start my React webpage it automatically goes from the home page to the authentication dashboard and starts refreshing.
I'm guessing it's a problem with React Router but I'm not really sure about this either?
This is how my App.js App component currently looks, which has the main Route functionality.
const App = () => {
const [auth, setAuth] = useState(false);
useEffect(() => {
localStorage.setItem("user", auth);
}, [auth]);
return (
<div className="landing" style={{zIndex:0, margin:"0px", position:"fixed"}}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
{!auth && (
<Route
path="/auth"
element={
<Auth authenticate={(val) => setAuth(val === 1 ? true : false)} />
}
/>
)}
{auth && (
<>
<Route path="/dashboard" element={<Dashboard />} />
</>
)}
<Route
path="*"
element={<Navigate to={auth ? "/dashboard" : "/auth"} />}
/>
</Routes>
</div>
);
}
And this is how my Home.js Home component file looks like
function Home() {
return (
<div className="main">
<div className="landingImageDiv">
<img src={ligaLogo} alt="uchisvg" className="landingImage" />
<div id="fade" className="linkDiv topMargin5">
<div>
<Link to="/about" className="popupLink">
<span className="hover">[About]</span>
</Link>
</div>
<div>
<Link to="/auth" className="popupLink">
<span className="hover">[Talent Network]</span>
</Link>
</div>
<div>
{/* Format to request access to platform */}
<a href="https://forms.gle/vKzq5M9n56oKKV5DA" className="popupLink">
<span className="hover">[Request RSO Onboarding]</span>
</a>
</div>
</div>
</div>
<div className="landing" id="fade">
<div style={{ zIndex: 5, position: "relative" }}></div>
</div>
</div>
);
}
Change your route definition as follows:
{
!auth ? (
<Route
path="/auth"
element={
<Auth authenticate={(val) => setAuth(val === 1 ? true : false)} />
}
/>
) : (
<>
<Route path="/dashboard" element={<Dashboard />} />
</>
);
}

How to use Chakra UI Fade transition in react router dom?

I am making a project using ChakraUI and React. So what I wanted to do is that to add some small animations in my project. Trying to implement the ChakraUI Fade component with react router dom, but I don't know how to use it properly.
So my sidebar has multiple options. These options may or may have submenus in it. What I wanted to do is that, when someone clicks in the option or any submenu, it will load the page after the Fade transition.
What I have done so far in my sidebar component
const SidebarTitle = () => {
return (
<>
<Box
width='200px'
height='160px'
textAlign='start'
bgColor='#473198'
px={5}
borderRadius={2}
>
<Text fontSize='2xl' color='white' fontFamily='Fjord One'>
some text
</Text>
</Box>
</>
);
};
export default function Sidebar() {
const [selectedSubMenu, setSelectedSubMenu] = useState("");
const handleClick = (title) => {
if (title === selectedSubMenu) {
setSelectedSubMenu("");
} else {
setSelectedSubMenu(title);
}
};
return (
<div>
<Box
display='flex'
justifyContent='flex-start'
alignItems='flex-start'
mb={10}
>
<Box>
<SidebarTitle />
{sidebarItems.map((items) => {
return (
<Box
width='200px'
textAlign='start'
cursor='pointer'
onClick={() => {
handleClick(items.title);
}}
fontFamily='Fjord One'
boxShadow='lg'
_hover={{
bgColor: "#1a2963",
color: "white",
}}
key={items.title}
>
<Link
to={items.url}
as={RouterLink}
width='100%'
_focus={{
boxShadow: "none",
}}
style={{ textDecoration: "none" }}
>
<Text fontSize='xl'>{items.title}</Text>
</Link>
<Collapse
in={items.title === selectedSubMenu}
transition={{ enter: { delay: 0.1 }, exit: { delay: 0.1 } }}
>
{items.subMenu?.map((item) => {
return (
<Box
bgColor='#e4e8e5'
boxShadow='md'
textAlign='start'
width='200px'
color='black'
_hover={{
bgColor: "#666666",
color: "white",
}}
key={item.title}
onClick={(event) => {
event.stopPropagation();
}}
>
<Link
to={item.url}
as={RouterLink}
width='100%'
_focus={{
boxShadow: "none",
}}
style={{ textDecoration: "none" }}
>
<Text fontFamily='Fjord One'>{item.title} </Text>
</Link>
</Box>
);
})}
</Collapse>
</Box>
);
})}
</Box>
<Box width='100%'>
<Routes>
<Route path='/' element={<Home />} />
<Route
path='about'
element={<about />}
/>
<Route
path='product'
element={<product />}
/>
<Route
path='dummy-link'
element={<dummy-link />}
/>
<Route path='dummy-link' element={<dummy-link />} />
<Route path='dummy-link' element={<dummy-link />} />
<Route path='dummy-link' element={<dummy-link />} />
<Route path='dummy-link' element={<dummy-link />} />
</Routes>
</Box>
</Box>
</div>
);
}
Can someone help me on how to implement the Fade transition in react router dom?

ReactJS Router not navigating to the specified component

I am pretty new to react-router. I created a single page with nav bars that can navigate to the either of two pages. In one of the pages, I have a series of link that should direct to another component. My app component deals with the initial routing
<Router>
<nav className ="nav">
<Link to='/' className="nav__nav-link-logo link"><img src={Logo} className="nav__nav-logo" alt="A figure that depicts school"></img></Link>
<button onClick={this.handleBarClick} className="nav__nav-bar-icon link"><FontAwesomeIcon icon={faBars} /></button>
<div className="nav__text-and-icon" style={{display : this.state.navTextDisplay}}>
<Link to = '/' className="nav__text link"><FontAwesomeIcon icon={faHome} className="icon" /> Home </Link>
<Link to = '/pages/Contact/Contact' className="nav__text link"><FontAwesomeIcon icon={faPhoneAlt} className="icon"/> Contact the Dev</Link>
</div>
</nav>
<Switch>
<Route exact path='/' component = { Home } />
<Route exact path='/' component = { Home } />
<Route path='/pages/Contact' component = { Contact } />
<Route component={NotFoundPage}/>
</Switch>
</Router>
then the home component renders a list of links I want to navigate to another component entirely. PS : this is not about nest routing
my list of links code is
render() {
return (
<Fragment>
{/**
* #param item the indiviual school generated from the API
*/}
{this.state.apiResponse.map((item, index) => {
return (
<Fragment>
<li key={item.schoollid}>
<Link
to="/component/SchoolDetails/SchoolDetails"
className="each-school"
>
<SchoolTemplate item={item} />
</Link>
</li>
<Route
path="/component/SchoolDetails"
render={props => (
<SchoolDetails {...props} details={item} />
)}
// component={SchoolDetails}
/>
</Fragment>
);
})}
</Fragment>
);
But then my routes is linking the individual links to my 404 (not found page)
Try this it worked for me ,
User Navbar React bootstrap plugin for the menu bar navigation ,
npm package: import {Navbar, Nav,NavItem, NavDropdown, MenuItem,Glyphicon, Label} from 'react-bootstrap';
`
</Navbar.Header>
<Navbar.Collapse>
<Nav>
<NavItem eventKey={1} href="#/Dashboard">
Dashboard
</NavItem>
<NavDropdown eventKey={3} title="Tickets" id="basic-nav-dropdown">
<MenuItem eventKey={3.1}>
<NavLink exact to={ "/Home"}>Home</NavLink>
</MenuItem>
<MenuItem eventKey={3.2}>
<NavLink exact to={ "/Gallary"}>Gallary</NavLink>
</MenuItem>
</Nav>
</NavDropdown>
</Navbar.Collapse>
<NavDropdown eventKey={3} title="Tickets" id="basic-nav-dropdown">
<MenuItem eventKey={3.1} ><NavLink exact to={"/Home"} >Home</NavLink></MenuItem>
<MenuItem eventKey={3.2}><NavLink exact to={"/Gallary"}>Gallary</NavLink></MenuItem>
</Nav>
npm package:
import {Route, BrowserRouter,NavLink,HashRouter , Switch} from 'react-router-dom';
`
try this.
class APIRoutes extends React.Component {
...
render() {
return (
<Switch>
{this.state.apiResponse.map((item, index) => {
return (
<Fragment>
...
<Route
path="/component/SchoolDetails"
render={props => (
<SchoolDetails {...props} details={item} />
)}
/>
</Fragment>
);
})}
</Switch>
);
}
And the component that have Router
<Router>
...
<Switch>
<APIRoutes />
<Route exact path='/' component={Home}/>
<Route path='/pages/Contact' component={Contact}/>
<Route component={NotFoundPage}/>
</Switch>
</Router>

React Router Link is Showing Two Components

I didn't know the best way to describe this issue, but I'm going to try and explain as best I can.
In my core React App component, i'm doing a conditional render, based on if a user is logged in.
If Logged In --- I show the main page, and if not, they get the login screen.
On my login page, i'm trying to put in a link at the bottom which directs a user to signup for a new account. My issue that when I click to this 'newuser' page, it is rendering both my login form and the create user form, both different components (see below).
I suspect this is an issue with how I have my react router setup, but I'm not sure what the problem is.
Here is the code in my App component.
<Container>
<Router>
<Notification />
{props.loggedUser ? (
<div>
<Navbar />
<Route exact path="/" render={() => <Blogs />} />
<Route exact path="/blogs" render={() => <Blogs />} />
<Route path="/login" render={() => <Login />} />
<Route
exact
path="/blogs/:id"
render={({ match }) => (
<Blog
blog={blogById(match.params.id)}
user={props.loggedUser}
/>
)}
/>
<Route exact path="/users" render={() => <Users />} />
<Route
exact
path="/users/:id"
render={({ match }) => <User user={userById(match.params.id)} />}
/>
</div>
) : (
<>
<Login />
</>
)}
</Router>
<div>
<br />
<em>Blog app, John 2019</em>
</div>
</Container>
And here is my Login component. I've tried including the route for the new users page on both sides of the conditional statement above and then also in the Login Form below, as I have now. All are leading to the same issue.
<h1>Login To Blog Application</h1>
<Form onSubmit={handleLogin}>
<Form.Field>
<label>username</label>
<input {...username.omitreset} name="username" />
</Form.Field>
<Form.Field>
<label>password</label>
<input {...password.omitreset} type="password" />
</Form.Field>
<Button type="submit">login</Button>
<div>
<br />
<Link to="/newuser">or signup to become a new user</Link>
<Route path="/newuser" render={() => <NewUser />} />
</div>
</Form>
</>
and NewUser component
import React from "react";
import { connect } from "react-redux";
import { createUser } from "../reducers/userReducer";
import { setNotification } from "../reducers/notificationReducer";
import { Form, Button } from "semantic-ui-react";
const NewUser = props => {
const addUser = event => {
event.preventDefault();
const userObject = {
username: event.target.username.value,
name: event.target.name.value,
password: event.target.password.value
};
event.target.username.value = "";
event.target.name.value = "";
event.target.password.value = "";
props.createUser(userObject);
};
return (
<>
<h1>Create a New Blog Account</h1>
<Form onSubmit={addUser}>
<Form.Field>
<label>username</label>
<input {...props.username} name="username" />
</Form.Field>
<Form.Field>
<label>name</label>
<input {...props.name} type="password" />
</Form.Field>
<Form.Field>
<label>password</label>
<input {...props.password} type="password" />
</Form.Field>
<Button type="submit">login</Button>
</Form>
</>
);
};
const mapDispatchToProps = {
createUser,
setNotification
};
export default connect(null, mapDispatchToProps)(NewUser);
you shouldn't do conditional rendering, because when the user is not logged the Loggin component is rendered and is not depended on the path at all. then you change the path by clicking Link to="/newuser" and the Sign up renders inside
I got this working based on det2dachoppa's recommendations. Removed the conditional and added the Switch and redirects to ensure that a user can't view the pages without logging in.
<Router>
<Notification />
<div>
<Navbar />
<Switch>
{props.loggedUser && (
<React.Fragment>
<Route exact path="/">
<Blogs />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/blogs">
<Blogs />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route
exact
path="/blogs/:id"
render={({ match }) => (
<Blog
blog={blogById(match.params.id)}
user={props.loggedUser}
history={props.history}
/>
)}
/>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/users">
<Users />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route
exact
path="/users:id "
render={({ match }) => (
<User user={userById(match.params.id)} />
)}
/>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/newblog">
<NewBlog />
</Route>
</React.Fragment>
)}
<Route path="/login">
<Login />
</Route>
<Route path="/newuser">
<NewUser />
</Route>
<Redirect to="/login">
<Login />
</Redirect>
</Switch>
</div>
</Router>

Categories

Resources