React Admin Layout Component From Scratch - reactjs

I want to implement a customized Layout for react-admin. I've tried to use their documentation 'https://marmelab.com/react-admin/Theming.html#using-a-custom-layout'
But it didn't work well ( for example we didn't have theme in our component). There is a broken link in the documentation that says you can use it for customizing :(.
I've implemented something right now that works fine right now but I don't know would work completely without problem/side-effects till the end of the project.
import * as React from 'react'
import { MuiThemeProvider, withStyles, createStyles} from '#material-ui/core/styles'
import appTheme from '../config/Theme'
import AppBar from './AppBar'
import Navbar from './Navbar'
const styles = (theme: any) => createStyles({
appFrame: {
display: 'flex',
flexDirection: 'column',
overflowX: 'auto',
},
content: {
display: 'flex',
flexDirection: 'column',
flexGrow: 2,
marginTop: '4em',
padding: theme.spacing.unit * 3,
paddingLeft: 5,
},
contentNoSidebar: {
display: 'flex',
flexGrow: 1,
},
root: {
backgroundColor: theme.palette.background.default,
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
position: 'relative',
zIndex: 1,
},
})
class CustomLayout extends React.Component<any, any> {
public render () {
const {
children,
classes,
logout,
open,
title,
} = this.props
return (
<MuiThemeProvider theme={appTheme}>
<div className={classes.root}>
<div className={classes.appFrame}>
<AppBar title={title} open={open} logout={logout} />
<Navbar/>
<main className={classes.contentNoSidebar}>
<div className={classes.content}>
{children}
</div>
</main>
</div>
</div>
</MuiThemeProvider>
)
}
}
export default withStyles(styles)(CustomLayout)
I appreciate if you could help me in this case.

I see nothing wrong with this code sample. This is indeed the way to go to customize the Layout. Do you have any issue with it ?
Can you open an issue on the react-admin repository about the documentation broken link ?

Related

How to 'justify-content: center' for MUI Pagination?

I am trying to center the contents of the Pagination. However, this does not work. On console, I need to justify the ul wrapper and I can not find any information on MUI site related to the pagination props or a guide on how to center the item.
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Pagination from '#material-ui/lab/Pagination';
const useStyles = makeStyles((theme) => ({
root: {
'& > *': {
marginTop: theme.spacing(2),
},
},
pagination: {
alignItems: 'center',
justify: 'center',
}
}));
const Paginated = (props) => {
const classes = useStyles();
return (
<div className={classes.root}>
<Pagination className={classes.pagination} count={props.totalPage} color='primary' />
</div>
);
};
export default Paginated;
and I have been trying on codesandbox as well. https://codesandbox.io/s/material-demo-zv1ps?file=/demo.js
Is there any way I can do this without having an additional box or Grid wrapper to wrap it out?
root: {
"& > *": {
marginTop: theme.spacing(2),
justifyContent:"center",
display:'flex'
}
}
We can also use Stack component:
import Stack from '#mui/material/Stack';
<Stack alignItems="center">
<Pagination className={classes.pagination} count={props.totalPage} color='primary' />
</Stack>
margin: "auto" worked for me
root: {
margin: "auto",
},
I got the idea from here: 4 ways to center a component in Material-UI

React Create a Horizontal Divider with Text In between

I need to create a React component that is a Horizontal Divider with a content like text In between. All the resources I have online is unable to help me get this done. I tried a material-ui divider by creating a Divider component and placing my text in-between like the example below:
<Divider>Or</Divider>
But I get the error:
hr is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.
I need to achieve this in the image below:
Any help will be appreciated.
These are my codes below:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import List from '#material-ui/core/List';
import Divider from '#material-ui/core/Divider';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
maxWidth: 360,
backgroundColor: theme.palette.background.paper,
},
}));
export default function ListDividers() {
const classes = useStyles();
return (
<List component="nav" className={classes.root} aria-label="mailbox
folders">
<Divider>Or</Divider>
</List>
);
}
Using Material UI.
import React from "react";
import { makeStyles } from "#material-ui/core";
const useStyles = makeStyles(theme => ({
container: {
display: "flex",
alignItems: "center"
},
border: {
borderBottom: "2px solid lightgray",
width: "100%"
},
content: {
paddingTop: theme.spacing(0.5),
paddingBottom: theme.spacing(0.5),
paddingRight: theme.spacing(2),
paddingLeft: theme.spacing(2),
fontWeight: 500,
fontSize: 22,
color: "lightgray"
}
}));
const DividerWithText = ({ children }) => {
const classes = useStyles();
return (
<div className={classes.container}>
<div className={classes.border} />
<span className={classes.content}>{children}</span>
<div className={classes.border} />
</div>
);
};
export default DividerWithText;
You can import and use it like the below
<DividerWithText>Or</DividerWithText>
Result
Here a custom example of what you could do : repro on stackblitz
import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import "./style.css";
const App = () => {
return <Divider>Or</Divider>;
};
const Divider = ({ children }) => {
return (
<div className="container">
<div className="border" />
<span className="content">
{children}
</span>
<div className="border" />
</div>
);
};
render(<App />, document.getElementById("root"));
And the CSS:
.container{
display: flex;
align-items: center;
}
.border{
border-bottom: 1px solid black;
width: 100%;
}
.content {
padding: 0 10px 0 10px;
}
Update 29/03/2022
That's now possible with Material UI 🔥
https://mui.com/components/dividers/#dividers-with-text
You may want different spacing sometime
<Divider spacing={1}>Hello World</Divider>
Or
<Divider spacing={2}>Hello World</Divider>
For a configurable spacing here a Github Gist
Or a playground in codesandbox if you prefer
The current answer causes any text with spaces in-between to wrap:
If that happens, changing width: 100% to flexGrow: 1 should solve it:
border: {
borderBottom: "2px solid lightgray",
flexGrow: 1,
}
Unfortunately for now, having Divider with text on it in MUI is only available in v5, which is still in alpha stage. If you would like to try, you can download the alpha package, but be warned that it is still highly unstable and a lot of changes might be needed to migrate to v5, which is not very worth it.
GitHub discussion: https://github.com/mui-org/material-ui/issues/24036

Hook API Styles aren't loading?

The project is being built with Next.js and material-ui. I've used the Hook API method to style my components but the styles aren't always loading. When I run next dev to test it, my styles don't load. If I edit anything in the page currently being rendered, it reloads, but this time with the styles. If I click reload, however, the styles fail to load again. I've been searching for help with this but I can't find anything that seems to solve the issue. I saw a few things about using material-ui/core with material-ui/styles but it's all in reference to v3 and it doesn't solve the issue I have.
Here's one of the pages for example:
import Nav from '../components/nav';
import Footer from '../components/footer';
import Product from '../components/product';
import { makeStyles, ThemeProvider } from '#material-ui/core/styles';
import theme from '../components/customTheme';
import {
Typography,
Button
} from '#material-ui/core';
const useStyles = makeStyles({
body: {
margin: '15vh 0',
backgroundColor: ' white',
textAlign: 'left'
},
earnWrapper: {
display: 'block',
textAlign: 'left',
backgroundColor: 'white',
width: '80%',
margin: '5% 2vh',
padding: '5%',
borderRadius: '25px',
transition: '0.3s',
boxShadow: '0px 5px 20px #dedede'
},
earnContent: {
textAlign: 'left',
display: 'inline-block'
},
earntCaption: {
color: 'grey',
},
earntAmount: {
margin: '1vh 0 2vh'
},
shareInfo: {
margin: '5% 2vh',
textAlign: 'left'
},
products: {
textAlign: 'center ',
width: '100%'
}
});
export default function Home(props) {
const styles = useStyles();
return (
<ThemeProvider theme={theme}>
<DefaultHead
title="Oorigin | Home"
/>
<Nav isLoggedIn={true} />
<div className={styles.body}>
<div className={styles.earnWrapper}>
<div className={styles.earnContent}>
<Typography className={styles.earntCaption} variant="caption">You've earned</Typography>
<Typography className={styles.earntAmount} variant="h4">S$18.50</Typography>
<Button disableElevation variant="contained" color="primary">Withdraw</Button>
</div>
</div>
<div className={styles.shareInfo}>
<Typography><b>Shop, Share, Earn</b></Typography>
<Typography><br/>Shop products you like, share products you love, and earn up to 10% commission on every qualifying sale you refer</Typography>
</div>
<div className={styles.products}>
<Product
imgURL="../TestItem1.svg"
imgAlt="Test Product"
title="Disinfecting Air Purifying Solution"
price={(22.80).toFixed(2)}
link="/products/staticProduct"
/>
<Product
imgURL="../TestItem2.svg"
imgAlt="Test Product"
title="Disinfecting Air Purifying Solution"
price={(22.80).toFixed(2)}
/>
<Product
imgURL="../TestItem3.svg"
imgAlt="Test Product"
title="Disinfecting Air Purifying Solution"
price={(22.80).toFixed(2)}
/>
<Product
imgURL="../TestItem4.svg"
imgAlt="Test Product"
title="Disinfecting Air Purifying Solution"
price={(22.80).toFixed(2)}
/>
</div>
</div>
<Footer/>
</ThemeProvider>
);
}

Pass multiple props to component in react-materialui

I'm trying to pass the styles and text to the reactjs component using PropTypes, but I'm getting the error that TypeError: Cannot read property 'header' of undefined and its point the error to {typo.header}
Unable to pass 2 different props into react component. I'm sure I'm not passing the props correctly, I'm learning reactjs and not sure how to do this correctly. Can some guide me how to do this.
App.js:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Card, { CardActions, CardContent } from 'material-ui/Card';
import Typography from 'material-ui/Typography';
import './App.css';
import { AppStyle } from "./AppStyle";
import { Typos } from "./AppTypo";
function SurveyApp(props) {
const { classes, typo } = props;
return (
<div className={classes.wrapper}>
<div className={classes._header}>
</div>
<div className={classes._body}>
<div className={classes.__formContainer}>
<Card className={classes.card}>
<CardContent>
<Typography>
{typo.header}
</Typography>
<Typography>
</Typography>
</CardContent>
</Card>
</div>
</div>
</div>
);
}
SurveyApp.propTypes = {
classes: PropTypes.object.isRequired,
typo: PropTypes.object.isRequired
}
export default withStyles(AppStyle, Typos)(SurveyApp);
AppStyle.js:
export const AppStyle = {
wrapper: {
width: '100%',
height: '100%',
position: 'relative'
},
_header: {
width: '100%',
height: 100,
backgroundColor: '#295e94',
position: 'relative'
},
_body: {
width: '100%;',
height: 'auto',
minHeight: 'calc(100% - 100px)',
position: 'relative',
display: 'flex',
flexDirection: 'row',
alignContent: 'center',
alignItems: 'start',
justifyContent: 'center'
},
__formContainer: {
width: 750,
position: 'absolute',
top: -30
},
'#media (max-width: 480px)': {
__formContainer: {
width: '100%',
position: 'absolute',
top: -30
}
}
}
AppTypo.js:
export const Typos = {
header: "User Experience",
subHeader: "This is intended to improve your experience."
}
You're not providing the props correctly.
export default withStyles(AppStyle, Typos)(SurveyApp);
Does not do what you think it does with Typos.
Besides that, you have two different definitions for header: header and _header. The style you pass via withStyles is _header, from AppStyle. That's the one you should use.
You should not try to pass non-style information via withStyles, which is what it looks like you're trying to do with Typos. Those need to come in from the parent component, or since this is the parent, just use the imported Typos.header.
I recommend you read more on props in general to get a better idea of what they are for an how to use them.
In the future, you may find using React's Context is better for handling styles.

How can i resolve this error in React+Material UI

I'm getting the following error while tried to run the application in Mac and Ubuntu. But it runs without any errors in Windows platform. How can i resolve this. Is there any platform specific code in Material UI beta version(v1.0.0-beta.46). I have used the withStyles component, which is an higher order component of material ui.
Error:
/node_modules/material-ui/styles/withStyles.js
Module not found: Can't resolve '#babel/runtime/core-js/map'
The below is my code
import React from 'react';
import PropTypes from 'prop-types';
import withStyles from 'material-ui/styles';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import Avatar from 'material-ui/Avatar';
import classNames from 'classnames';
import AppIcon from '../../assets/img/myAppIcon.png';
const styles = theme => ({
root: {
flexGrow: 1,
},
flex: {
flex: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
loginButton:{
alignContent: "flex-end"
},
avatar: {
margin: 10,
},
toolbar: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: '0 8px',
...theme.mixins.toolbar,
},
content: {
flexGrow: 1,
backgroundColor: theme.palette.background.default,
padding: theme.spacing.unit * 3,
},
});
// Here is my functional component which renders the AppBar with login button at the right hand side.
function Layout(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar
position="absolute"
className={classNames(classes.appBar)}
>
<Toolbar>
<Avatar src={AppIcon} className={classes.avatar} />
<Typography variant="title" color="inherit" noWrap>
MyApp
</Typography>
<Typography variant="title" color="inherit" noWrap className={classes.flex} />
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
<main className={classes.content}>
<div className={classes.toolbar} />
{props.children}
</main>
</div>
);
}
Layout.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
//Here I'm getting an error on executing this
export default withStyles(styles, { withTheme: true })(Layout);
You Can use this, It will be working.
npm install #babel/runtime
Try the beta version
npm install #babel/runtime#7.0.0-beta.55

Resources