useState not working in next js with material ui drawer - reactjs

useState not working. I have searched for a solution I checked many forms like https://github.com/vercel/next.js/issues/7626 , https://github.com/vercel/next.js/issues/17592 ,
Hooks error: Invalid Hook Call using NextJS or ReactJS on Windows , some people seem to suggest that it can be solved by removing a node module that they did not mention the name of, others says it works if they change their webpack configurations but i have never used webpack and couldn't find they mentioned so I am stuck.
I was implementing material ui's drawer, i have created a drawer component and imported it.
Nav.jsx:
import React, { useState } from 'React'
import SignedOutLinks from "./Links/SignedOutLinks"
import { AppBar, Toolbar } from "#material-ui/core"
import MenuBtn from "./Links/MenuBtn"
import Logo from "./Links/Logo"
import CategoryBtn from "./Links/CategoryBtn"
import ShoppingCartBtn from "./Links/ShoppingCartBtn"
import LanguageBtn from "./Links/LanguageBtn"
import DarkModeBtn from "./Links/DarkModeBtn"
import NotificationBtn from "./Links/NotificationBtn"
import SignedIn from "./Links/SignedIn"
import Grid from '#material-ui/core/Grid';
import Search from "./Search/Search"
import { useTheme } from '#material-ui/core/styles';
import useMediaQuery from '#material-ui/core/useMediaQuery';
import Drawer from './Drawer/Drawer'
const signedIn = true
const Nav = () => {
const [isOpened, setIsOpened] = useState(false)
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.down("sm"))
const handleDrawerToggle = () => {
setIsOpened(!isOpened)
}
return (
<AppBar color="transparent" elevation={0} >
<Toolbar>
{
!isMobile?
<Grid
container
direction="row"
justify="space-between"
alignItems="center"
spacing={10}
>
<Grid item container spacing={5} xs={4} justify="flex-start" wrap="nowrap">
<Grid item>
<Logo/>
</Grid>
<Grid item>
<CategoryBtn />
</Grid>
</Grid>
<Grid item xs={4}>
<Search />
</Grid>
<Grid item container xs={4} justify="flex-end" wrap="nowrap">
<ShoppingCartBtn />
<LanguageBtn />
<DarkModeBtn />
<NotificationBtn />
{signedIn? <SignedIn /> : <SignedOutLinks />}
</Grid>
</Grid>
:
<div>
<Drawer isOpened={isOpened} />
<Grid
container
direction="row"
justify="space-around"
spacing={10}
>
<Grid item container xs={4} justify="flex-start">
<MenuBtn handleClick={handleDrawerToggle} />
</Grid>
<Grid item Container xs={4} justify="center" style={{textAlign: "center"}}>
<Grid item>
<Logo />
</Grid>
</Grid>
<Grid item container xs={4} justify="flex-end">
<ShoppingCartBtn />
</Grid>
</Grid>
</div>
}
</Toolbar>
</AppBar>
)
}
export default Nav
Drawer.jsx:
import { Drawer as MUIDrawer} from '#material-ui/core'
import { List, ListItem,ListItemText, ListItemIcon } from '#material-ui/core'
import NotificationsIcon from '#material-ui/icons/Notifications';
import TranslateIcon from '#material-ui/icons/Translate';
import Brightness4Icon from '#material-ui/icons/Brightness4';
import LocalShippingIcon from '#material-ui/icons/LocalShipping';
import AccountCircleIcon from '#material-ui/icons/AccountCircle';
import BusinessIcon from '#material-ui/icons/Business';
import ExitToAppIcon from '#material-ui/icons/ExitToApp';
import ChatBubbleOutlineIcon from '#material-ui/icons/ChatBubbleOutline';
import CategoryIcon from '#material-ui/icons/Category';
function Drawer({isOpened}) {
const items = [
{
text: user.userName,
icon: <AccountCircleIcon />
},
{
text: "Categories",
icon: <CategoryIcon />
},
{
text: "Language",
icon: <TranslateIcon />
},
{
text: "Mode",
icon: <Brightness4Icon />
},
{
text: "Notifications",
icon: <NotificationsIcon />
},
{
text: "Orders",
icon: <LocalShippingIcon />
},
{
text: "Are You a Seller?",
icon: <BusinessIcon />
},
{
text: "Messages",
icon: <ChatBubbleOutlineIcon />
},
{
text: "Logout",
icon: <ExitToAppIcon />
}
]
return (
<div>
<MUIDrawer open={isOpened}>
<List>
{
items.map(item => {
return (
<ListItem button key={item.text} >
{item.icon && <ListItemIcon>{item.icon}</ListItemIcon>}
<ListItemText primary={item.text} />
</ListItem>
)
})
}
</List>
</MUIDrawer>
</div>
)
}
export default Drawer
Note it was working fine until i coded the Drawer, also useState is imported at the very beginning ing so i didn't forget to import it
Edit:
Folder Structure in next.js
index.js:
import Head from 'next/head'
import styles from '../styles/Home.module.css'
import Nav from '../Components/Navbar/Nav'
export default function Home() {
return (
<>
<Head>
<meta name="description" content="Everything for everyone. TRNC E-commerce website focused on a huge variety of categories from fashion to electronics. Order now and get your product delivered." />
</Head>
<div className={styles.container}>
<Nav />
</div>
</>
)
}

Its finally working, however I couldn't find the problem. I solved it by literaly creating a new component called Nav2 that i copied the same code from the original Nav component from and voila it worked, i deleted the old Nav component and renamed Nav2 to Nav and it kept working.
Note: i found that i forgot to import useContext in the drawer as user is an deconstructed object that is sent from _app.js so i added
const { user } = useContext(UserContext)
to the beginning of the component function

Related

Google maps doens't load in my react app (feat, GoogleMapReact)

I'm trying to make a react app that loads a google map.
but somehow the map doesn't show and not an error was reported in console logs....
import React from 'react'
import GoogleMapReact from 'google-map-react'
import {Paper, Typography, useMediaQuery} from '#material-ui/core'
import LocationOnOutlinedIcon from '#material-ui/icons/LocationOnOutlined'
import Rating from '#material-ui/lab'
import useStyles from './styles'
const Map = () => {
const classes = useStyles()
const isMobile = useMediaQuery('(min-width:600px)')
const coordinates = { lat:0, lng: 0}
return (
<div className={classes.mapContainer}>
<GoogleMapReact
bootstrapURLKeys={{ key: 'AIzaSyBrSAzFufdmJBVojpd7idemPVGp8HskFKY' }}
defaultCenter={coordinates}
center={coordinates}
defaultZoom={14}
margin={[50,50,50,50]}
>
</GoogleMapReact>
</div>
)
}
export default Map
ㄴ this is Map.js file
import Header from "./components/Header/Header";
import {List} from "./components/List/List";
import Map from "./components/Map/Map";
import {CssBaseline, Grid} from '#material-ui/core';
function App() {
return (
<div className="App">
<CssBaseline></CssBaseline>
<Header/>
<Grid container spacing={3} style={{ width: '100%'}}>
<Grid item xs={12} md={4}>
<List/>
</Grid>
<Grid item xs={12} md={8}>
<Map/>
</Grid>
</Grid>
</div>
);
}
export default App;
ㄴthis is App.js file
enter image description here
What's causing the error(if that is an error)?
j
How can I make the map show up in my app?

Why material-ui components don't display in my App?

So I'm following a react tutorial and in that project material-ui is being used, it's e-commerce, so I have Products.jsx and Product.jsx files.
Product.jsx file:
import React from 'react';
import { Card, CardMedia, CardContent, CardActions, Typography, IconButton} from '#material-ui/core';
import { AddShoppingCart } from '#material-ui/icons';
import MuiThemeProvider from '#material-ui/core/styles/MuiThemeProvider';
const Product = ( {product} ) => {
return (
<MuiThemeProvider>
<Card className="rootie">
<CardMedia className="media" image='' title={product.name} />
<CardContent>
<div className="cardContent">
<Typography variant="h5" gutterBottom>
{product.name}
</Typography>
<Typography variant="h5" gutterBottom>
{product.price}
</Typography>
</div>
<Typography variant="h2" color="textSecondary">{product.description}</Typography>
</CardContent>
<CardActions disableSpacing className="cardActions">
<IconButton aria-label="Add to cart">
<AddShoppingCart/>
</IconButton>
</CardActions>
</Card>
</MuiThemeProvider>
);
}
export default Product;
Products.jsx:
import React from 'react';
import { Grid } from '#material-ui/core';
import Product from '../Product/Product';
import MuiThemeProvider from '#material-ui/core/styles/MuiThemeProvider';
const products = [
{ id: 1, name: 'JBL', description: 'JBL', price: '$100'},
{ id: 2, name: 'AirPods', description: 'AirPods', price: '$100'},
];
const Products = () => {
return (
<MuiThemeProvider>
<Grid container justifyContent="center" spacing={4}>
{products.map((product) =>{
<Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
<Product product={product}/>
</Grid>
})}
</Grid>
</MuiThemeProvider>
);
}
export default Products;
And my App.js looks like this:
import React from 'react';
import Header from './components/Header/Header';
import Products from './components/Products/Products';
import './App.scss';
const App = () => {
return (
<div>
<Products/>
</div>
)
}
export default App;
So as you see, everything looks okay, but for some reason React doesn't render the components, so the page looks empty. I've searched on the internet and found about 'MuiThemeProvider', but adding it didn't really help either.
You need to create a theme and pass it as prop to ThemeProvider which in turn wraps the entire App during ReactDOM.render stage itself. Something like this:
import * as React from 'react';
import ReactDOM from 'react-dom';
import CssBaseline from '#mui/material/CssBaseline';
import { ThemeProvider } from '#mui/material/styles';
import App from './App';
import theme from './theme';
ReactDOM.render(
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<App />
</ThemeProvider>,
document.querySelector('#root'),
);
Only then will your Material UI components work as you expect.

Dynamic data are not rendering on the browser

Good day, I'm trying to create a MEARN stack application with react-redux. I am already able to post data to my MongoDB atlas, and I am also able to fetch the data and console.log it. But when I try to render the data to my front end the browser returns an empty page. I would like to know what is causing this issue. This is my first time creating a react application.
import './Experience.css';
import Post from './Posts/Post';
import { Grid, CircularProgress } from '#material-ui/core';
import { useSelector } from 'react-redux';
function Experience() {
const posts = useSelector((state) => state.posts);
console.log(posts); //Logged my data on DevTool -> Console (see image below)
return (
!posts.length ? <CircularProgress /> : (
<Grid container alignItems="stretch" spacing={3}>
Test //view browser
{posts.map((post) => (
<Grid key={post._id} item xs={3} >
<Post post={post} />
</Grid>
))}
</Grid>
)
);
}
export default Experience;
import React from 'react';
import { Card, CardActions, CardContent, CardMedia, IconButton, Typography, CardHeader, Avatar } from '#material-ui/core';
import MoreVertIcon from '#material-ui/icons/MoreVert';
const Post = ({ post }) => {
return (
<Card>
<CardMedia image={post.companyLogo} />
<CardHeader
avatar={
<Avatar aria-label="recipe">
<img href={post.employerImage}/>
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={post.employerName}
subheader={post.jobTitle}
/>
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">{post.responsibility.map((tag) => `🖱️${tag} `)}</Typography>
</CardContent>
<CardActions>
<Typography variant="body2" color="textSecondary" component="p">{post.employedDate}</Typography>
</CardActions>
</Card>
);
}
export default Post;
Since you are getting response from the db, there must be a rendering error.
From a quick look I see that you have missused the Avatar component.
It should be like: <Avatar alt="recipe" src={post.employerImage} />
or if you want to utilize the children prop, img tag takes src not href:
<Avatar aria-label="recipe">
<img src={post.employerImage}/>
</Avatar>

How to use Material UI's ThemeProvider with next.js?

I want to pallete of the theme for my next.js app.
I'm very new to next.js so please be kind. I can give more info if something specific is required.
This is my index.js
import Navbar from "../src/components/navbar";
import Frontpage from "../src/components/frontpage ";
import { Grid, ThemeProvider, createMuiTheme } from "#material-ui/core";
const theme = createMuiTheme({
pallete: {
primary: {
main: '#abcdef',
}
}
})
function Index() {
return (
<ThemeProvider theme={theme}>
<Grid container justify="center" style={{ scrollBehavior: "smooth" }}>
<Grid item xs={9}>
<Navbar />
<Frontpage />
</Grid>
</Grid>
</ThemeProvider>
);
}
export default Index;
This is my Frontpage.js
import Grid from "#material-ui/core/Grid";
import { Button } from "#material-ui/core";
import styles from "../styles/_homeview.module.scss";
const Frontpage = () => {
return (
<>
<Grid item className={styles.homehead}>
Heading 1
</Grid>
<Grid item xs={6} className={styles.homeTagLine}>
lorem ipsum for, lets say around 30 words
</Grid>
<Button variant="contained" color="primary">
Contact Us
</Button>
</>
);
};
export default Frontpage;
Here I expect the button to be of color specified in the theme (#abcdef) but its the default Material UI theme color.
How can I fix (apply/modify) the default Material UI theme?
There is a typo - palette not pallete in your example!
const theme = createMuiTheme({
palette: {
primary: {
main: '#abcdef',
}
}
})

Which React Material-UI components add a spacing to my page (like a row class in Bootstrap)?

I've created a project using React and Material-UI for React.
Coming from a Bootstrap background, I've noticed none of these components come with any margin around their components.
In Bootstrap I can add spacing like this:
<div class="row">
<div class="col-xs-12">
...
</div>
</div>
But I've got no idea what component to use to create such spacing.
I'm currently using custom classes to create some sort of spacing, but it doesn't feel correct.
App.tsx:
<Container maxWidth="lg" className="container-padding">
...
</Container>
App.css:
.container-padding {
padding: 30px;
}
For example, add spacing between these elements with an existing component:
I'm open for suggestions.
There is a grid layout component in #material-ui similar to Bootstrap grid. Both are based on a 12-column grid.
The below example demonstrates it,
import Box from '#material-ui/core/Box';
import Grid from "#material-ui/core/Grid";
import Paper from "#material-ui/core/Paper";
return (
<Box m={4}>
<Grid container spacing={3}>
<Grid item xs={6}>
<Paper>xs=6</Paper>
</Grid>
<Grid item xs={6}>
<Paper>xs=6</Paper>
</Grid>
<Grid item xs={3}>
<Paper>xs=3</Paper>
</Grid>
<Grid item xs={3}>
<Paper>xs=3</Paper>
</Grid>
<Grid item xs={3}>
<Paper>xs=3</Paper>
</Grid>
<Grid item xs={3}>
<Paper>xs=3</Paper>
</Grid>
</Grid>
</Box>
<Box mx={3}>
Box 2 content
</Box>
<Box my={3}>
Box 3 content
</Box>
);
So to summarize,
m - all sides margin
mx - Horizontal spacing
my - Vertical spacing
I've used the "Lobotomized Owl" selector by Heydon Pickering: * + *.
I created a 'container' component Vertical.js:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import { Box } from '#material-ui/core';
const useStyles = makeStyles((theme) => ({
vertical: {
'& > *+*': {
marginTop: '1.5rem',
},
},
}));
const Vertical = ({ children }) => {
const classes = useStyles();
return <Box className={classes.vertical}>{children}</Box>;
};
export default Vertical;
Then use it in any other components e.g. Example.js:
import React from 'react';
import Vertical from './Vertical';
const Example = () => {
return (
<Vertical>
<Component/>
<Component />
<Another />
<AnotherComponent />
</Vertical>
);
};
export default Example;

Resources