I'm getting that error Uncaught TypeError: Cannot read properties of undefined (reading 'push')
. I've seen some other posts about it but I'm still stuck. I'm using react-router-dom v6. I think it has something to do with passing the props or something like that. The immediate place it's happening is in the "Home" page, if the Login button is clicked, the error will happen and the browser will not redirect to the Login page. Here's my file hierarchy
src
components
Dashboard
Dashboard.js
Home
Home.js
Login
Login.js
Panel
Panel.js
App.js
index.js
The home page has a button to go to the login page. The login page has a button to go to Dashboard. Dashboard has a button to go to Panel.
Here's the code index.js
import App from "./components/App";
App.js
import React, { Component } from "react";
import { render } from 'react-dom';
import Login from "./Login/Login";
import Home from "./Home/Home";
import Dashboard from "./Dashboard/Dashboard";
import Panel from "./Panel/Panel";
import {
BrowserRouter as Router,
Routes,
Route,
} from "react-router-dom";
export default class App extends Component {
constructor(props){
super(props)
}
render(){
return(
<Router>
<Routes>
<Route path="/frontend/" element={<Home />}></Route>
<Route path="/frontend/panel" element={<Panel />} />
<Route path="/frontend/login" element={<Login />}/>
<Route path="/frontend/dashboard" element={<Dashboard />}/>
</Routes>
</Router>
);
}
}
const appDiv = document.getElementById("app");
render(<App />, appDiv);`
Home
import React from 'react';
import { Container, Button } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles({
root: {
marginLeft: "auto",
marginRight: "auto",
width: "54%",
textAlign: "center"
},
});
const Home = (props) => {
const handleLoginClick = () => {
props.history.push('/frontend/login');
}
const classes = useStyles();
return (
<Container className={classes.root}>
<h1>Home Page</h1>
<Button variant="contained" onClick={handleLoginClick}>Login</Button>
</Container>
)
}
export default Home;
Login
import React, { useState } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import {
Card,
CardMedia,
CardContent,
CardActions,
TextField,
Button
} from '@material-ui/core';
import './Login.css';
const useStyles = makeStyles({
root: {
marginLeft: "auto",
marginRight: "auto",
width: "40%",
},
media: {
height: 100,
width: 250,
marginLeft: "auto",
marginRight: "auto",
},
signInButton: {
marginLeft: "auto",
marginRight: "auto"
}
});
const Login = (props) => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const classes = useStyles();
const handleLogin = () => {
props.history.push('/frontend/dashboard');
}
return (
<div>
<Card className={classes.root}>
<CardMedia className={classes.media} image="../../../static/images/some_image.jpg" title="Some Image"/>
<CardContent>
<TextField type="text" placeholder="Username" variant="filled" fullWidth></TextField>
<TextField type="password" placeholder="Password" variant="filled" fullWidth></TextField>
</CardContent>
<CardActions>
<Button variant="contained" className={classes.signInButton} onClick={handleLogin}>Sign In</Button>
</CardActions>
</Card>
</div>
);
}
export default Login;
Dashboard.js
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
//import { getUser, removeUserSession } from './Utils/Common';
import Drawer from '@material-ui/core/Drawer';
import CssBaseline from '@material-ui/core/CssBaseline';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import List from '@material-ui/core/List';
import Typography from '@material-ui/core/Typography';
import Divider from '@material-ui/core/Divider';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import { Button } from '@material-ui/core';
const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
},
appBar: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
},
drawer: {
width: drawerWidth,
flexShrink: 0,
},
drawerPaper: {
width: drawerWidth,
},
// necessary for content to be below app bar
toolbar: theme.mixins.toolbar,
content: {
flexGrow: 1,
backgroundColor: theme.palette.background.default,
padding: theme.spacing(3),
},
}));
const Dashboard = (props) => {
const classes = useStyles();
//const user = getUser();
const handleLogout = () => {
//removeUserSession();
props.history.push('/frontend');
}
const handleClickCreateGraphs = () => {
props.history.push('/frontend/panel');
}
return(
<div>
<CssBaseline />
<AppBar position="fixed" className={classes.appBar}>
<Toolbar>
<Typography variant="h6" noWrap>
Welcome
</Typography>
</Toolbar>
</AppBar>
<Drawer
className={classes.drawer}
variant="permanent"
classes={{
paper: classes.drawerPaper,
}}
anchor="left"
>
<div className={classes.toolbar} />
<Divider />
<List>
<ListItem button key="View Graphs">
<ListItemText primary="View Graphs" />
</ListItem>
<ListItem button key="Create Graphs" onClick={handleClickCreateGraphs}>
<ListItemText primary="Create Graphs" />
</ListItem>
</List>
<Divider />
<Divider />
<Button variant="contained" onClick={handleLogout}>Logout</Button>
</Drawer>
</div>
)
}
export default Dashboard;
Panel
The panel page is way too long to post here and irrelevant to the issue. Right now, it has no onclick events to take you to another page
CodePudding user response:
In react-router-dom
V6 you can use useNavigate
hook for programmatic navigation, like this:
Home
...
import { useNavigate } from "react-router-dom";
...
const Home = (props) => {
const navigate = useNavigate();
const handleLoginClick = () => {
navigate('/frontend/login');
}
...
}