link changes but page does not - reactjs

react-router changes the link but the page does not change. When go to the address from URL it works but doesn't work when clicking button
ZWrapper.jsx
import React from 'react';
import { Link, NavLink } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { withStyles, createStyleSheet } from 'material-ui/styles';
import ZWrapperAppBar from 'app/components/Wrapper/ZWrapperAppBar';
import ZWrapperDrawer from 'app/components/Wrapper/ZWrapperDrawer';
const styleSheet = createStyleSheet('Main', {
root: {
width: '100%',
flexGrow: 1,
align: 'center',
direction: 'row'
},
flex: {
align: 'center',
direction: 'row',
justify: 'flex-end',
},
mainDrawer:{
position: 'relative',
width: 500
},
mainDrawerContent:{
height: '100%'
},
mainDrawerBottomNav:{
position: 'absolute',
bottom: 0
},
typeContainer:{
margin: 0
}
});
export class ZWrapper extends React.Component{
PropTypes = {
classes: PropTypes.object.isRequired,
};
render(){
return(
<div className={styleSheet.root}>
<ZWrapperAppBar classes={styleSheet} />
<ZWrapperDrawer classes={styleSheet} />
{this.props.children}
</div>
)
}
}
// export default withStyles(styleSheet)(ZWrapper);
export default connect((state)=>{
return { drawerOpen: state.mainContainerDrawerOpen }
})(ZWrapper);
ZWrapperAppBar.jsx
import React from 'react';
import { Link, NavLink } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { withStyles, createStyleSheet } from 'material-ui/styles';
import { AppBar, Toolbar, Typography, IconButton, Grid, Button } from 'material-ui';
import { lightGreen, green } from 'material-ui/colors';
import MenuIcon from 'material-ui-icons/Menu';
import LinkButton from 'app/components/material-ui-addons/LinkButton';
import {toggleOpenDrawer} from 'actions';
export class ZWrapperAppBar extends React.Component{
PropTypes = {
classes: PropTypes.object.isRequired,
};
render(){
var {dispatch, drawerOpen, classes} = this.props;
return(
<AppBar position="absolute" >
<Toolbar style={{backgroundColor: green.A400}} className={classes.mainAppBar}>
<IconButton color="contrast" aria-label="Menu" onClick={()=>{dispatch(toggleOpenDrawer())}}>
<MenuIcon />
</IconButton>
<Typography color="inherit" type="title">
Recipea
</Typography>
<Grid container className={classes.flex} align="center" direction="row" justify="flex-end" gutter={Number("8")}>
<Button component={Link} color="contrast" to="/Account/Login" >{'Get Started'}</Button>
</Grid>
</Toolbar>
</AppBar>
)
}
}
export default connect((state)=>{
return { drawerOpen: state.mainContainerDrawerOpen }
})(ZWrapperAppBar);
ZWrapperDrawer
import React from 'react';
import { Link, NavLink } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { withStyles, createStyleSheet } from 'material-ui/styles';
import { AppBar, Toolbar, Typography, Button, IconButton, Grid, Drawer, Divider } from 'material-ui';
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List';
import BottomNavigation, { BottomNavigationButton } from 'material-ui/BottomNavigation';
import { lightGreen, green, grey } from 'material-ui/colors';
import CloseIcon from 'material-ui-icons/Close';
import SettingsIcon from 'material-ui-icons/Settings';
import FavoriteIcon from 'material-ui-icons/Favorite';
import LocationOnIcon from 'material-ui-icons/LocationOn';
import ListItemWithLink from 'app/components/material-ui-addons/ListItemWithLink';
import {toggleOpenDrawer} from 'actions';
export class ZWrapperDrawer extends React.Component{
PropTypes = {
classes: PropTypes.object.isRequired,
};
render(){
var {dispatch, drawerOpen, classes} = this.props;
return(
<Drawer docked={false} open={drawerOpen} onRequestClose={()=>{dispatch(toggleOpenDrawer())}} className={classes.mainDrawer}>
<AppBar position="static" className={classes.mainAppBar}>
<Toolbar style={{backgroundColor: green.A400}}>
<Link to="/">
<Button>
<Typography type="title" style={{color: grey[50]}}>Recipea</Typography>
</Button>
</Link>
<Grid container className={classes.flex} align="center" direction="row" justify="flex-end" gutter={Number("8")}>
<IconButton color="contrast" aria-label="Menu" onClick={()=>{dispatch(toggleOpenDrawer())}}>
<CloseIcon />
</IconButton>
</Grid>
</Toolbar>
</AppBar>
<ListItem button>
<ListItemText primary="About" />
</ListItem>
<ListItemWithLink to="/About/Us" label="Us" />
<ListItemWithLink to="/About/OurHelper" label="Used Dependencies"/>
<BottomNavigation className={classes.mainDrawerBottomNav} showLabels>
<BottomNavigationButton label="Settings" icon={<SettingsIcon />} />
<BottomNavigationButton label="Favorites" icon={<FavoriteIcon />} />
<BottomNavigationButton label="Nearby" icon={<LocationOnIcon />} />
</BottomNavigation>
</Drawer>
)
}
}
export default connect((state)=>{
return {
drawerOpen: state.mainContainerDrawerOpen
}
})(ZWrapperDrawer);
My Router
import React from 'react';
import {BrowserRouter as Router, Switch, Route, Redirect} from 'react-router-dom';
import MainPage from 'MainPage';
import ZWrapper from 'ZWrapper';
import AccountSignUp from 'AccountSignUp';
export default(
<Router>
<ZWrapper>
<Switch>
<Route exact path='/' component={MainPage}/>
<Route exact path='/Account/SignUp' component={AccountSignUp}/>
</Switch>
</ZWrapper>
</Router>
)
app.jsx
//Modules
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
// import 'typeface-roboto';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import injectTapEventPlugin from 'react-tap-event-plugin';
// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin();
import Router from 'app/router/';
import {configure} from 'configureStore';
var store = configure();
//App CSS
require('applicationStyles');
//App JS
require('myJS/all.jsx');
// override material-ui theme
const theme = createMuiTheme({
overrides:{
MuiGrid:{
'gutter-xs-8':{
margin: '0 -8px'
},
'gutter-xs-16':{
margin: '0 -8px'
},
'gutter-xs-24':{
margin: '0 -8px'
},
'gutter-xs-40':{
margin: '0 -8px'
},
},
},
})
//render
ReactDOM.render(
<Provider store={store}>
<MuiThemeProvider theme={theme}>
{Router}
</MuiThemeProvider>
</Provider>,
document.getElementById('app')
);
Material-UI: v1-alpha
React: 15.5.4
React-router-dom: 4.1.1
Browser: chrome (59.0.3071.115)

Add change the folowing code to add withRouter to from react-router-dom and change the export default to solve this issue
import { Link, NavLink, withRouter } from 'react-router-dom';
export default withRouter(
connect((state)=>{
return { drawerOpen: state.mainContainerDrawerOpen }
})(ZWrapperDrawer)
);

Related

I'm getting an "Uncaught TypeError: Cannot read properties of undefined (reading 'push')" with react-router-dom v6

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
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');
}
...
}

Material UI makeStyles inside a TSX Class Component

How can I make use of the Material UI styling options inside of a TSX class-component?
Due to the Typed Props and State I can't seem to figure out how to do it.
My Code below throws an "Invalid hook" error in side the componentWillMount method, where I try to load the created styles in to my component state.
How would you go about using the Material UI makeStyles method in a TSX component?
import { makeStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardMedia from '#material-ui/core/CardMedia';
import CardContent from '#material-ui/core/CardContent';
import CardActions from '#material-ui/core/CardActions';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import { IShowMinimal } from "../../interface/show.minimal";
interface IShowCardProps {
show: IShowMinimal
}
interface IShowCardState {
materialUIclasses: any
}
const useStyles = makeStyles({
card: {
maxWidth: 345,
},
media: {
height: 140,
},
});
export class ShowCard extends Component<IShowCardProps, IShowCardState> {
constructor(props: IShowCardProps) {
super(props);
console.log("hi");
this.state = {
materialUIclasses: {}
}
console.log("Show", this.props.show);
}
componentWillMount() {
this.setState({
materialUIclasses: useStyles({})
});
}
render(): JSX.Element {
return (
<article>
<Card>
<CardActionArea>
<CardMedia
className={this.state.materialUIclasses.media}
image={this.props.show.image}
title={`Thumbnail for the show ${this.props.show.name}`}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{this.props.show.name}
</Typography>
</CardContent>
</CardActionArea>
</Card>
</article>
)
}
}```
makeStyles returns react hook, so you can't use it inside Component. Hooks are only for functional components. Use withStyles HOC from material-UI.
import { withStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardMedia from '#material-ui/core/CardMedia';
import CardContent from '#material-ui/core/CardContent';
import CardActions from '#material-ui/core/CardActions';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import { IShowMinimal } from "../../interface/show.minimal";
interface IShowCardProps {
show: IShowMinimal,
classes: any
}
interface IShowCardState {
materialUIclasses: any
}
const styles = {
card: {
maxWidth: 345,
},
media: {
height: 140,
},
};
class ShowCard extends Component<IShowCardProps, IShowCardState> {
constructor(props: IShowCardProps) {
super(props);
this.state = {
materialUIclasses: {}
}
}
render(): JSX.Element {
return (
<article>
<Card>
<CardActionArea>
<CardMedia
className={this.props.classes.media}
image={this.props.show.image}
title={`Thumbnail for the show ${this.props.show.name}`}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{this.props.show.name}
</Typography>
</CardContent>
</CardActionArea>
</Card>
</article>
)
}
}
export default withStyles(styles)(ShowCard);

How to reduce height of ListSubheader in Material-UI?

I have a
<ListSubheader className={this.props.classes.listSubHeaderRoot}>Teszt Színház</ListSubheader>
in a List.
And set style like:
const styles = theme => ({
// ...
listSubHeaderRoot: {
backgroundColor: '#E5E5E5',
color: '#252525',
height: '22px'
/* To change the font, use the fontFamily rule */
}
})
but result looks like:
Why text is out of the grace box? How can I prevent it?
Here the whole code:
import React, { Component } from "react";
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import ArrowForwardIos from '#material-ui/icons/ArrowForwardIos';
import ListSubheader from '#material-ui/core/ListSubheader';
import Switch from '#material-ui/core/Switch';
import TextField from '#material-ui/core/TextField';
import ListItemAvatar from '#material-ui/core/ListItemAvatar';
import Avatar from '#material-ui/core/Avatar';
import FolderIcon from '#material-ui/icons/Folder';
import ListItemSecondaryAction from '#material-ui/core/ListItemSecondaryAction';
import DeleteIcon from '#material-ui/icons/Delete';
import IconButton from '#material-ui/core/IconButton';
import Box from '#material-ui/core/Box';
import { withStyles } from '#material-ui/core/styles';
const styles = theme => ({
listSubHeaderRoot: {
backgroundColor: '#E5E5E5',
color: '#252525',
height: '22px'
/* To change the font, use the fontFamily rule */
}
})
class App extends Component {
render() {
return <div>
<ListSubheader className={this.props.classes.listSubHeaderRoot}>Teszt Színház</ListSubheader>
<ListItem button>
<Box textAlign="left" style={{width: 150 }}>Teszt Esemény</Box>
<ListItemText secondaryTypographyProps={{ align: "right" }} secondary=""/>
<IconButton edge="end" aria-label="delete">
<ArrowForwardIos />
</IconButton>
</ListItem>
</div>;
}
}
export default withStyles(styles)(App);
Need to set:
lineHeight: "22px"

How to convert 'Functional Componenet' to 'Class Component' in React?

I would like to convert this Functional Component
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/core/Menu';
import FacebookLoginButton from "./components/FacebookLoginButton"
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
}));
function App() {
const classes = useStyles();
return (
<div className="App">
<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
Tiket.hu
</Typography>
<Button color="inherit">Search</Button>
<Button color="inherit">Basket</Button>
<FacebookLoginButton/>
</Toolbar>
</AppBar>
</div>
);
}
export default App;
to Class Component, like below here, but I get an error. Do you know what is wrong?
import React, { Component } from "react";
import logo from './logo.svg';
import './App.css';
import { makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/core/Menu';
import FacebookLoginButton from "./components/FacebookLoginButton"
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
}));
class App extends Component {
classes = useStyles();
render() {
return <div className="App">
<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={this.classes.menuButton} color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" className={this.classes.title}>
Tiket.hu
</Typography>
<Button color="inherit">Search</Button>
<Button color="inherit">Basket</Button>
<FacebookLoginButton/>
</Toolbar>
</AppBar>
</div>;
}
}
export default App;
Do you know what is wrong? How should I convert differently?
You must use the material ui HOC with a class component
import React, { Component } from "react";
import logo from './logo.svg';
import './App.css';
import { makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/core/Menu';
import FacebookLoginButton from "./components/FacebookLoginButton"
// import this
import { withStyles } from '#material-ui/core/styles';
// make this
const styles = theme => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
})
class App extends Component {
render() {
return <div className="App">
<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={this.props.classes.menuButton} color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" className={this.props.classes.title}>
Tiket.hu
</Typography>
<Button color="inherit">Search</Button>
<Button color="inherit">Basket</Button>
<FacebookLoginButton/>
</Toolbar>
</AppBar>
</div>;
}
}
export default withStyles(styles)(App);
Material-ui MakeStyles is using the hook pattern, which is not allowed inside class components.
Use withStyles HOC instead.
import { withStyles } from '#material-ui/core/styles';
const styles = {
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
};
class App extends Component {
const { classes } = this.props;
the rest of your component...
}
export default withStyles(styles)(App);
You are using hooks inside a Class Component this isn't allowed. Hooks are specifically made to work with Functional Components

Reactjs.NET - Props is undefined and stuck on why?

So i'm still finding my feet with reactjs.net + asp.net core. I've imported latest version (v1) of material-ui.com into the mix. I am trying to combine the two but having issues with classes/props composition.
The code below is verbatim of what i've been told i need and found via hours of searching online. Yet, this.props.classes continue to throw undefined errors.
Is there a step i'm missing?
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
const homeStyles = {
root: {
height: 200 ,
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
export class Home extends React.Component {
displayName = Home.name
constructor(props) {
super(props);
console.log("Props: " + props != null);
}
render() {
const { classes } = this.props;
return (
<div>
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton style={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" style={classes.grow}>Undefined? {(this.props == undefined).toString()}</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</div>
</div>
);
}
}
Home.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(homeStyles)(Home)

Resources