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.
Related
I am new to React and material UI. I am using material UI button and I want to remove default button classes (MuiButtonBase-root MuiButton-root MuiButton-text makeStyles-buttonCss-3). I want to use only my class 'buttonCss'. Please can anyone help me to fix this.
My code is below -:
import { TextField } from '#material-ui/core';
import Button from '#material-ui/core/Button';
import { makeStyles } from '#material-ui/core/styles'
import { Form, Formik } from 'formik';
import * as React from 'react';`enter code here`
const useStyles = makeStyles((theme) => ({
container: {`enter code here`
maxWidth: "100vw",
maxHeight: "100vh",
display: "flex",
alignItems: "flex-start",
justifyContent: "space-evenly",
flexWrap: 'wrap'
},
mybox: {
width: 300,
backgroundColor: theme.palette.success.main,
color: "white",
padding: theme.spacing(1),
borderRadius: 4,
boxShadow: theme.shadows[10]
},
buttonCss : {
backgroundColor: theme.palette.success.dark
},
deafult: {
color: 'red'
}
}));
// implementing button this way
<Button className={classes.buttonCss} >Submit</Button>
You can't remove the default class and then continue using MaterialUi, now just use the default html button .
If you want only to customise, now just use
const useStyles = makeStyles({
root: {background: "red}
});
export default () => {
const classes = useStyles();
return <Button className={classes} >Submit</Button>
}
I am trying to understand how to override the CSS/formatting/theme for just a single React component in a Typescript/React/MaterialUI/JSS project. Below is the code, however the {classes.gridStyle} within the JSX doesn't get processed (see screenshot below the code snippet). I can see it show up in the browser debugger as unmodified and the typescript editor is also giving me a warning that variable "classes" is never used.
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import { Grid, createStyles } from '#material-ui/core';
const useStyles = makeStyles(() =>
createStyles({
gridStyle: {
display: 'inline-block',
padding: '0 20px',
height: '40px',
},
'& div': {
display: 'inline-block',
fontSize: '10px',
padding: '0 20px',
height: '40px',
},
})
);
export default function HomeHeader(): JSX.Element {
const classes = useStyles();
return (
<Grid item className="{classes.gridStyle}">
Row 1 completely override css experiment...
</Grid>
);
}
Issue inside browser debugger
className="{classes.gridStyle}">
should be
className={classes.gridStyle}>
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
I have a progressBar component. The initial animation refuses to work in spite of setting initialAnimation to true. What am I missing?
Are there any extra CSS needed to fix it?
I just want the initialAnimation on the graph and number need not change
import React from 'react'
import CircularProgressbar from 'react-circular-progressbar'
import { withStyles } from '#material-ui/core/styles'
import Typography from '#material-ui/core/Typography'
import PropTypes from 'prop-types'
const styles = theme => ({
progressBar: {
width: '80px',
margin: 'auto',
marginTop: theme.spacing.unit + 4,
marginBottom: theme.spacing.unit + 4,
position: 'relative'
},
text: {
position: 'absolute',
top: 20,
left: 5,
paddingRight: '5px'
}
});
function StyledProgressbar(props) {
const { classes, palette } = props;
return (
<div className={classes.progressBar}>
<Typography variant="caption" align='center' className={classes.text}>
{props.percentage}% complete
</Typography>
<CircularProgressbar
percentage={props.percentage}
strokeWidth={10}
initialAnimation={true}
styles={{
path: {
stroke: palette.secondary.main,
strokeLinecap: 'round',
transition: 'stroke-dashoffset 0.5s ease 0s',
},
trail: {
stroke: palette.secondary.light,
strokeLinecap: 'round',
}
}}>
</CircularProgressbar>
</div>
);
}
StyledProgressbar.propTypes = {
classes: PropTypes.object,
percentage: PropTypes.number,
palette: PropTypes.object
}
export default withStyles(styles)(StyledProgressbar);
you just need to change this:
import CircularProgressbar from 'react-circular-progressbar';
from this:
import { CircularProgressbar } from 'react-circular-progressbar';
for more information refrence
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 ?