I am trying to export styled AppBar,this is my code
import * as React from 'react';
import { styled, useTheme } from '#mui/material/styles';
import MuiAppBar from '#mui/material/AppBar';
import Toolbar from '#mui/material/Toolbar';
import Typography from '#mui/material/Typography';
import MenuIcon from '#mui/icons-material/Menu';
const MuiAppBar = styled(MuiAppBar, {
shouldForwardProp: (prop) => prop !== 'open',
})(({ theme, open }) => ({
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
...(open && {
marginLeft: drawerWidth,
width: `calc(100% - ${drawerWidth}px)`,
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
}),
}));
const AppBar = () => {
return (
<div>
<MuiAppBar position="fixed" open={open}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
sx={{
marginRight: '36px',
...(open && { display: 'none' }),
}}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap component="div">
Mini variant drawer
</Typography>
</Toolbar>
</MuiAppBar>
</div>
)
}
export default AppBar
This is giving pre-declared error
Line 12:7: Parsing error: Identifier 'MuiAppBar' has already been declared.
You cannot import:
import MuiAppBar from '#mui/material/AppBar';
and then create a function expression with the same name. Just change the name of your function expression to something else and use that name in your jsx
example:
const CustomMuiAppBar = .....
///
<CustomMuiAppBar />
You have declared The appBar Styled function with the same name. You are already importing MuiAppBar from mui. You must choose another name for your custom function. For example:
import MuiAppBar from '#mui/material/AppBar';
const CustomAppBar = styled()
Here the custom function name is different from the default one. Try this, It should work.
Related
I am a react beginner. I use hooks in the class and the program reports errors
src\page\App.js
Line 41:35: React Hook "React.useState" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
Line 44:39: React Hook "React.useState" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
Search for the keywords to learn more about each error.
this is my code
import './App.css';
import React from "react";
import {BottomNavigation, BottomNavigationAction} from "#material-ui/core";
import {AccountCircle, Home, Info} from "#material-ui/icons";
import makeStyles from "#material-ui/core/styles/makeStyles";
import Grid from "#material-ui/core/Grid";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import styled from "#material-ui/core/styles/styled";
class App extends React.Component {
render() {
makeStyles(() => ({
title: {
color: "#ffffff"
},
toolbar: {
background: "#3f51b5"
},
contents: {
marginBottom: "100px"
},
bottomNavigation: {
left: '0px',
right: '0px',
position: 'fixed',
bottom: '0px',
}
}));
const {classes} = this.props
const MyGrid = styled(Grid)({
marginTop: 10,
});
//切换标签选中的钩子
const [value, setValue] = React.useState('home');
//切换toolbar的钩子
const [tbValue, setTbValue] = React.useState("主页");
const handleChange = (event, newValue) => {
setValue(newValue);
console.log("switch" + newValue)
//切换tb的字
switch (newValue) {
case 'home':
setTbValue("主页");
this.props.history.push('/home/user_login');
break;
case 'info':
setTbValue("信息");
this.props.history.push('/home/info');
break;
case 'me':
setTbValue("我的");
this.props.history.push('/home/me');
break;
}
};
return (
<div>
<AppBar position="static" style={{left: "0", right: "0"}}>
<Toolbar className={classes.toolbar}>
<Typography className={classes.title}>
{tbValue}
</Typography>
</Toolbar>
</AppBar>
{/*内容区*/}
<div className={classes.contents}>
<div>
<MyGrid container direction={'column'} justify={"center"}
alignContent={"center"}>
{this.props.children}
</MyGrid>
</div>
</div>
<BottomNavigation className={classes.bottomNavigation}
value={value}
onChange={handleChange} showLabels>
<BottomNavigationAction label="主页" value='home' icon={<Home/>}/>
<BottomNavigationAction label="信息" value='info' icon={<Info/>}/>
<BottomNavigationAction label="我的" value='me' icon={<AccountCircle/>}/>
</BottomNavigation>
</div>
);
}
}
export default App;
When i use method everything is normal
import './App.css';
import React from "react";
import {BottomNavigation, BottomNavigationAction} from "#material-ui/core";
import {AccountCircle, Home, Info} from "#material-ui/icons";
import makeStyles from "#material-ui/core/styles/makeStyles";
import Grid from "#material-ui/core/Grid";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import styled from "#material-ui/core/styles/styled";
function App(props) {
makeStyles(() => ({
title: {
color: "#ffffff"
},
toolbar: {
background: "#3f51b5"
},
contents: {
marginBottom: "100px"
},
bottomNavigation: {
left: '0px',
right: '0px',
position: 'fixed',
bottom: '0px',
}
}));
const {classes} = props
const MyGrid = styled(Grid)({
marginTop: 10,
});
//切换标签选中的钩子
const [value, setValue] = React.useState('home');
//切换toolbar的钩子
const [tbValue, setTbValue] = React.useState("主页");
const handleChange = (event, newValue) => {
setValue(newValue);
console.log("switch" + newValue)
//切换tb的字
switch (newValue) {
case 'home':
setTbValue("主页");
props.history.push('/home/user_login');
break;
case 'info':
setTbValue("信息");
props.history.push('/home/info');
break;
case 'me':
setTbValue("我的");
props.history.push('/home/me');
break;
}
};
return (
<div>
<AppBar position="static" style={{left: "0", right: "0"}}>
<Toolbar className={classes.toolbar}>
<Typography className={classes.title}>
{tbValue}
</Typography>
</Toolbar>
</AppBar>
{/*内容区*/}
<div className={classes.contents}>
<div>
<MyGrid container direction={'column'} justify={"center"}
alignContent={"center"}>
{props.children}
</MyGrid>
</div>
</div>
<BottomNavigation className={classes.bottomNavigation}
value={value}
onChange={handleChange} showLabels>
<BottomNavigationAction label="主页" value='home' icon={<Home/>}/>
<BottomNavigationAction label="信息" value='info' icon={<Info/>}/>
<BottomNavigationAction label="我的" value='me' icon={<AccountCircle/>}/>
</BottomNavigation>
</div>
);
}
export default App;
Using hooks in class component is not allowed. As stated in the react docs:
You can’t use Hooks inside a class component, but you can definitely mix classes and function components with Hooks in a single tree. Whether a component is a class or a function that uses Hooks is an implementation detail of that component. In the longer term, we expect Hooks to be the primary way people write React components.
Link: https://reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both
In the demo.js, I wanted to use the Card along with its CardHeader and put wordings inside the CardContent. Also, I will be using the CardComponent in other files as well. How can I make the CardComponent reusable?
Sample codes: https://codesandbox.io/s/basiccard-material-demo-forked-kkshx?file=/demo.js
Below are the codes for the demo.js:
import * as React from "react";
import CardComponent from "./CardComponent";
export default function BasicCard() {
return (
<>
<h1>Hello</h1>
<CardComponent />
</>
);
}
Below are the codes for the CardComponent:
import React from "react";
import Card from "#mui/material/Card";
import CardContent from "#mui/material/CardContent";
import { CardHeader } from "#mui/material";
const CardComponent = () => {
const CardStyle = {
maxWidth: 500,
margin: "0 auto",
marginBottom: "1rem",
marginTop: "1rem"
};
return (
<Card sx={{ minWidth: 275 }} elevation={5} style={CardStyle}>
<CardHeader title="Card Header Title here" />
<CardContent>//content here</CardContent>
</Card>
);
};
export default CardComponent;
I have another question as well under this component. Coming from material-ui4, mui5 was kind of confusing as I can no longer use the makeStyles. I tried adding this in the codesandbx example, however, it will say that dependency not found:
import { makeStyles } from '#mui/styles';
Hence, I settled with const CardStyle. Any help on how can I implement the newer version of the makeStyles? Also, do I need to install other dependecies from material-ui to make it work? Below is the package.json file.
Also in: https://www.reddit.com/r/reactjs/comments/sgqhh3/how_do_i_make_a_reusable_component_for_the_cards/
You can make it reusable adding props to your child card component. You can add as many props you want to make different cards using the same pattern.
To give styles to the component in mui v5 you have to use styled. You have to import it from #mui/material/styles
Here is the whole code of the new card component
import React from "react";
import {styled} from "#mui/material/styles"
import Card from "#mui/material/Card";
import CardContent from "#mui/material/CardContent";
import { CardHeader } from "#mui/material";
const StyledCard = styled((props) => (
<Card
{...props}
/>
))(({ theme }) => ({
maxWidth: 500,
margin: "0 auto",
marginBottom: "1rem",
marginTop: "1rem"
}));
const CardComponent = (props) => {
const {title,content}=props
return (
<StyledCard sx={{ minWidth: 275 }} elevation={5}>
<CardHeader title={title} />
<CardContent>{content}</CardContent>
</StyledCard>
);
};
export default CardComponent;
And here it is the whole codesandbox.
I am creating a Navbar in a Project. In my Project I use
mui/icons-material: ^5.2.5
mui/material: ^5.2.6
mui/styles: ^5.2.3
Now My folder structure is
Root.jsx
Navbar.jsx
styles.js
I am having an error of
The `styles` argument provided is invalid.
You are providing a function without a theme in the context.
One of the parent elements needs to use a ThemeProvider.
I have tried to fix with
Add ThemeProvider at Root.jsx
Remove from Root.jsx & Add at Navbar.jsx
& Others
Note: I don't know Material UI. Please help me to get out from this error. Here I am providing my code.
Code
Code of Root.jsx
import React from 'react'
import Navbar from './Navbar'
const Root = () => {
return (
<>
<Navbar />
</>
)}
export default Root
Code of Navbar.jsx
import React from 'react'
import { AppBar, Menu, MenuItem, Toolbar, Typography, IconButton, Badge } from '#mui/material'
import { ShoppingCart } from '#mui/icons-material'
import useStyles from './styles'
import Logo from '../../images/logo.png'
const Navbar = () => {
const classes = useStyles()
return (
<>
<AppBar className={classes.appBar} position='fixed' color='inherit'>
<Toolbar>
<Typography className={classes.title} variant='h6' color='inherit'>
<img className={classes.image} alt='Tech Cart' src={Logo} height='25px' />
Tech Cart
</Typography>
<div className={classes.grow} />
<div className={classes.button}>
<IconButton aria-label='Show cart products' color='inherit'>
<Badge badgeContent={2} color='secondary'>
<ShoppingCart />
</Badge>
</IconButton>
</div>
</Toolbar>
</AppBar>
</>
)
}
export default Navbar
Code of style.js
import {
makeStyles
} from '#mui/styles'
import {
alpha
} from '#mui/material/styles'
const drawerWidth = 0;
export default makeStyles((theme) => ({
appBar: {
boxShadow: 'none',
borderBottom: '1px solid rgba(0, 0, 0, 0.12)',
[theme.breakpoints.up('sm')]: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
},
},
title: {
flexGrow: 1,
alignItems: 'center',
display: 'flex',
textDecoration: 'none',
},
image: {
marginRight: '10px',
},
menuButton: {
marginRight: theme.spacing(2),
[theme.breakpoints.up('sm')]: {
display: 'none',
},
},
grow: {
flexGrow: 1,
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: alpha(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: alpha(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
width: 'auto',
},
},
searchIcon: {
padding: theme.spacing(0, 2),
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
inputRoot: {
color: 'inherit',
},
inputInput: {
padding: theme.spacing(1, 1, 1, 0),
// vertical padding + font size from searchIcon
paddingLeft: `calc(1em + ${theme.spacing(4)}px)`,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('md')]: {
width: '20ch',
},
},
}));
I also ran into this issue. These are the steps I followed to solve the issue:
Add following import in the component that will use mui:
import
Next, create a theme.
createTheme
Wrap the component within Themeprovider and pass the theme to it:
themeprovider
You need to use createTheme function from mui, https://mui.com/customization/theming/ Here you can watch examples. MakeStyles is used to style a specific component, but not the whole application.
so you need to do something like this:
const theme = createTheme({
//here you set palette, typography ect...
})
Then you wrap your whole application in ThemeProvider like this...
<ThemeProvider theme={theme}>
//Your application
</ThemeProvider>
and then, when you use makeStyles({theme}) your theme object will have your described theme values.
try this in your Root component:
import React from 'react';
import Navbar from './Navbar';
import {createTheme} from '#mui/material';
import {ThemeProvider} from '#maui/styles';
const Root = () => {
const theme = createTheme()
return (
<ThemeProvider theme={theme}>
<Navbar />
</ThemeProvider>
)}
export default Root
you can find more details in this link https://mui.com/material-ui/customization/theming/
I wrote my ThemeProvider in the MainLayout and then received this error message, then i took it in Index component as the parent of the MainLayout then it has been solved
To throw more light to #MAHDI's Answer
Do this:
import { ThemeProvider, makeStyles } from '#mui/styles'
import { createTheme, createTheme } from '#mui/material'
Create a function within your component wrapper:
const useStyles = makeStyles(theme => ({
...... jsx/js style properties .......
}));
function App(){
const theme = createTheme();
return (
<ThemeProvider theme={theme}>
..... Your children components ....
</ThemeProvider>
);
}
export default App;
I have created a theme in the index of my React.JS project using MUI. When I try to apply my style to my Appbar the theme does not correctly modify the menu button nor the menu itself. the button looks generic default and the menu remains white when it should match the color of the Appbar itself.
My index.tsx looks as such:
import React from "react";
import ReactDOM from "react-dom";
import AppbarTop from "./AppbarTop";
import { Router } from "react-router";
import { createBrowserHistory } from "history";
import AdapterDateFns from "#mui/lab/AdapterDateFns";
import { LocalizationProvider } from "#mui/lab";
import { createTheme } from "#mui/material";
import { ThemeProvider } from "#mui/styles";
import { StyledEngineProvider } from "#mui/material/styles";
const customHistory = createBrowserHistory();
const theme = createTheme({
palette: {
primary: {
main: "#242526"
},
secondary: {
main: "#d975d0"
},
text: {
primary: "#E4E6EB",
secondary: "#B0B3B8"
},
background: {
default: "#242526",
paper: "#242526"
}
}
});
ReactDOM.render(
<React.StrictMode>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Router history={customHistory}>
<ThemeProvider theme={theme}>
<StyledEngineProvider injectFirst>
<AppbarTop />
</StyledEngineProvider>
</ThemeProvider>
</Router>
</LocalizationProvider>
</React.StrictMode>,
document.getElementById("root")
);
My appbar.tsx looks like this:
import React from "react";
import {
AppBar,
Box,
Button,
Container,
Menu,
MenuItem,
Toolbar
} from "#mui/material";
import HomeIcon from "#mui/icons-material/Home";
import { makeStyles } from "#mui/styles";
const useStyles = makeStyles((theme?: any) => ({
appBar: {
background: theme.palette.primary.main,
height: "60px",
position: "relative"
}
}));
const AppbarTop: React.FC<{ [key: string]: any }> = () => {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState<any>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<>
<AppBar position="static" className={classes.appBar}>
<Toolbar>
<Button
id="basic-button"
aria-controls="basic-menu"
aria-haspopup="true"
aria-expanded={open ? "true" : undefined}
onClick={handleClick}
>
Dashboard
</Button>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "basic-button"
}}
>
<MenuItem onClick={handleClose}>
<HomeIcon />{" "}
</MenuItem>
</Menu>
{/*test speed dial*/}
<Container maxWidth="sm"></Container>
<Box></Box>
</Toolbar>
</AppBar>
</>
);
};
export default AppbarTop;
Can someone please explain what I am missing?
Change this line:
import { ThemeProvider } from "#mui/styles";
To:
import { ThemeProvider } from "#mui/material/styles";
Reason: There are 2 ThemeProviders here
The one from #mui/styles: This ThemeProvider does send the Theme object down via context, it works fine, you can still access it using the useTheme hook:
const theme = useTheme();
return <Box sx={{ width: 10, height: 10, bgcolor: theme.palette.primary.main }} />
The one from #mui/material/styles: This ThemeProvider is a wrapper of the above, but it also injects the theme to the StyledEngineThemeContext.Provider, which allows you to access the theme when using MUI API (sx prop/styled()). The problem here is that the Button and Menu components uses the styled() API under-the-hood so the ThemeProvider needs to be imported from #mui/material/styles to make it work.
return <Box sx={{ width: 10, height: 10, bgcolor: 'primary.main' }} />
Related answers
Difference between #mui/material/styles and #mui/styles?
Cannot use palette colors from MUI theme
MUI - makeStyles - Cannot read properties of undefined
Material UI Dark Mode
I want to let the drawer disappear behind my navbar when it is opened. Currently, the drawer is overlaying the navbar. I tried to change it with z-index in my "styles" but apparently it does not work (see screenshot). I set the z-index for the navbar higher than for the drawer.
Can you identify my mistake?
Here is the drawer.js:
import React from "react";
import clsx from "clsx";
import { makeStyles, useTheme } from "#material-ui/core/styles";
import Drawer from "#material-ui/core/Drawer";
const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
},
drawer: {
width: drawerWidth,
zIndex: 400,
flexShrink: 0,
/*whiteSpace: "nowrap",*/
},
drawerOpen: {
width: drawerWidth,
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
And here is my navbar.js:
// import packages
import React, { useContext, Fragment } from "react";
import { Link } from "react-router-dom";
// import local dependenceis
import Logo from "./images/tubot_logo.png";
import AuthContext from "../../Context/Auth/authContext";
// import material-ui
import withStyles from "#material-ui/core/styles/withStyles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
// styling
const styles = (theme) => {
return {
root: {
flexGrow: 1,
zIndex: 2000,
},
title: {
flexGrow: 1,
fontFamily: "shadowsintolight",
textDecoration: "none",
color: "black",
},
};
const Navbar = (props) => {
// destructuring: styling props
const {
root,
title,
} = props.classes;
// react: return jsx
return (
<div className={root}>
<AppBar position="absolute" >
<Toolbar>
/*some navbar stuff*/
</Toolbar>
</AppBar>
</div>
);
};
Try setting the classes prop on your Drawer component like this:
const App = () => {
const classes = useStyles();
return (
<div className="App" className={root}>
<AppBar position="absolute">
<Toolbar>
// Toolbar content...
</Toolbar>
</AppBar>
<Drawer
variant="persistent"
anchor="left"
open={true}
classes={{
paper: classes.drawer,
}}>
// Drawer content...
</Drawer>
</div>
);
};