Material UI changes style of components - javascript

Every time I render component, it's keep changing styles.
import React from 'react';
import FormControl from '#material-ui/core/FormControl';
import MenuItem from '#material-ui/core/MenuItem';
import Select from '#material-ui/core/Select';
import Button from '#material-ui/core/Button';
import { makeStyles } from "#material-ui/core/styles";
import sharedTheme from '../../styling/theme.js';
import { Icon } from '#twilio/flex-ui';
import { withStyles } from '#material-ui/core/styles';
import { makeInternalCall } from './index';
import { StylesProvider } from '#material-ui/core/styles';
import { createGenerateClassName } from '#material-ui/core/styles';
const styles = theme => (sharedTheme(theme));
class InternalDialpad extends React.Component {
.........
render() {
const { classes, manager } = this.props;
const { contact_uri: worker_contact_uri } =
manager.workerClient.attributes;
return (
<div className={classes.boxDialpad}>
<div className={classes.titleAgentDialpad}>Call Agent</div>
<div className={classes.subtitleDialpad}>Select agent</div>
<FormControl className={classes.formControl}>
<Select
value={this.state.selectedWorker}
onChange={this.handleChange}
isClearable
>
{this.state.workerList.map((worker)=> {
const { activity_name } = worker;
const { contact_uri, full_name } = worker.attributes;
return (
contact_uri !== worker_contact_uri &&
activity_name !== "Offline"
) ? (
<MenuItem value={contact_uri} key={contact_uri}>
{full_name}
</MenuItem>
) : null
}
)}
</Select>
<div className={classes.buttonAgentDialpad}>
<Button
variant="contained"
color="primary"
disabled={!this.state.selectedWorker}
onClick={this.makeCall}
className={classes.dialPadBtn}
>
<Icon icon="Call"/>
</Button>
</div>
</FormControl>
</div>
)
}
}
export default withStyles(styles)(InternalDialpad);
Theme.js
const sharedTheme = (theme) => ({
root: {
flexGrow: 1,
display: "flex",
flexWrap: "wrap",
},
main:{
margin: 0,
padding: 0
},
formControl: {
width: "250px",
},
boxDialpad: {
borderTop: "1px solid #eeeeee",
},
titleAgentDialpad: {
width: "100%",
textTransform: "uppercase",
textAlign: "center",
fontWeight: "bold",
fontSize: theme.typography.fontSize,
},
subtitleDialpad: {
textTransform: "uppercase",
},
buttonAgentDialpad: {
display: "flex",
justifyContent: "center",
},
dialPadBtn: {
borderRadius: "100px",
minWidth: "0px",
}
});
Now as expected, I can see styles classes are being assigned to each elements, but as soon as I render this component , it changes it's class name or add similar class to that element with additional css styles. Not sure why it is happening.

Material UI components are native HTML elements with additional styles applied as classes in order for them to achieve the clean look that they have out of the box.
Using the component <Button /> for instance is just shorthand for the MUI custom Button component implementation, which includes a native <input type="button" />, several <div />s, and more. Look in your browser dev tools at what renders to the DOM where you imported the MUI elements in your JSX.
The styles you are adding via classes.customClassName extends that default, but is not the only styling on the element. If you need to override these defaults, you can see which classes will be added to each element during render in the API section of each MUI component's documentation.

Related

Passing Data From One Component to Another React

Hey guys and gals i am trying to pass data from a text field in one component to another component. But the component that calls the text field is called in my Home.tsx file while i need the data from my Search.tsx file ( which also has where the text field is created ) to be sent to my searchResults.tsx file. Hope that makes sense
Here is my Home.tsx
import { ChakraProvider, Flex, Heading, IconButton, Input, Spacer, useColorMode, useDisclosure, VStack } from "#chakra-ui/react";
import Search from "../components/Search";
const Home = () => {
return(
<div>
<Flex>
<Search></Search>
</Flex>
</div>
)
}
export default Home
Here is my Search.tsx
import { TextField, IconButton} from "#material-ui/core"
import {Router, SearchOutlined } from '#material-ui/icons';
import { makeStyles } from "#material-ui/core/styles";
import "../App.css";
import { useState } from "react";
import { ChakraProvider,Box, color, position } from "#chakra-ui/react";
import { ReactComponent as Logo } from '../images/logo.svg';
const useStyles = makeStyles({
input: {
color: "blue"
}
})
const Search = () => {
const [searchTerm, setSearchTerm] = useState("");
const [displaySearchTerm, setDisplaySearchTerm] = useState("");
const useStyles = makeStyles((theme) => ({
input: {
color: "#fcba03",
},
}));
const classes = useStyles();
return(
<div>
<div className='searchCont' style={{alignItems: "center", justifyContent: 'center'}} >
<Logo style={{ height: 150, width: 300, position: "absolute", verticalAlign: "middle", marginTop: 200, left: '40%', backgroundColor: '#1a202c', borderRadius: 10 }} />
<TextField
inputProps={{color: classes.input}}
style={{width: 600, display: "flex", position: "absolute", verticalAlign: "middle", backgroundColor: "white", borderRadius: 5, alignItems: "center", justifyContent: 'center', marginTop: 400, marginBottom: 50, left: '32%', marginRight: 200}}
margin="normal"
className="textField"
fullWidth
id="standard-bare"
variant="outlined"
label="Search for Domains..."
onChange={(e) => setSearchTerm(e.target.value)}
InputProps={{
endAdornment: (
<IconButton onClick={() =>{searchTerm}}>
<SearchOutlined />
</IconButton>
),
}}
/>
</div>
</div>
)
}
export default Search
Here is my searchResults.tsx
import { Flex } from "#chakra-ui/react";
import React from "react";
import {searchTerm} from "../components/Search";
const SearchResults = () => {
return(
<div>
<Flex>
<Search data={searchTerm} /> //error here
</Flex>
</div>
)
}
export default SearchResults;
use Redux as your state management system for this, this will help you read and write states across application without worrying.
You can also try react Context if its a one off issue and you dont wana invest into the redux system and its boiler plate code, but if you face this issue more frequently as your project grows complex use redux.

What is the alternative of makeStyles for Material UI v.5

I just started using Material UI version 5. Originally to use my custom theme's styles, I would use makestyles, but it seems that does not work in v.5. My themes are on their own component, and to import those, I used {createTheme} instead of the old {createMuiTheme}. I have my theme imported into the Parent component as usual and have it set up as <ThemeProvider theme{theme}></ThemeProvider>.
Now, on my other component, I again was trying to use useStyles, but it was not working because it is not used in version 5. I am having a hard time trying to figure out how to convert it so that it can be used in version 5. Here is some of the unfinished code I was working on:
const useStyles = makeStyles((theme) => ({
logo: {
height: "8em",
marginLeft: "0.2em",
},
tabContainer: {
marginLeft: "auto",
},
tab: {
...theme.typography.tab,
minWidth: 10,
marginRight: "50px",
opacity: 1,
"&hover": {
color: theme.palette.common.purple,
textDecoration:"none",
},
},
}));
export default function Navigation(props) {
const classes = useStyles();
const [value, setValue] = useState(0);
const handleChange = (e, value) => {
setValue(value);
};
const refreshPage = () => {
window.location.reload();
};
useEffect(() => {
switch (window.location.pathname) {
case "/":
if (value !== 0) {
setValue(0);
}
break;
default:
break;
}
}, [value]);
return (
<React.Fragment>
<ElevationScroll>
<AppBar
position="relative"
style={{
borderBottom: "2px solid black",
}}
>
<Toolbar disableGutters>
<img src={logo} alt="nasa logo" className={classes.logo}/>
<Typography variant="h1" style={{ textAlign: "center" }}>
Nasa<br></br>Photos
</Typography>
<Tabs
value={value}
onChange={handleChange}
className={classes.tabContainer}
indicatorColor="primary"
>
<Tab
className={classes.tab}
component={Link}
onClick={refreshPage}
to="/"
label="Home"
/>
</Tabs>
</Toolbar>
</AppBar>
</ElevationScroll>
</React.Fragment>
);
}
I have read about the xs property and I have also heard of the styled() through Material UI's documentation, but I am having a hard time applying it to the code that I have written and would like a push in the right direction.
So to edit what I had earlier, I am going to also add my Theme.js file as well. I thought that this has been done correctly, but again it isn't reading my tab nor my palette.
import {createTheme} from "#mui/material/styles";
const pink = "#FFC0CB";
const lightblue = "#ADD8E6";
const purple = "#800080";
const black = "#000000";
const theme = createTheme({
palette: {
common: {
pink: pink,
lightblue: lightblue,
purple: purple,
black: black
},
primary: {
main: pink,
mainGradient: "linear-gradient(to left, purple, pink)",
},
secondary: {
main: lightblue,
mainGradient: "linear-gradient(to right, lightblue, pink)"
},
},
typography: {
tab: {
fontFamily:"Orbitron",
textTransform: "none",
fontSize: "2.5rem",
color: black,
},
h1: {
fontFamily: "Orbitron",
fontSize: "2.5em"
},
h2: {
fontFamily: "Orbitron",
fontSize: "2.5em"
},
subtitle1: {
fontFamily: "Orbitron"
},
subtitle2: {
fontFamily: "Orbitron",
fontSize: "1.5rem"
},
buttons: {
fontFamily: "Orbitron",
textTransform: "none"
},
},
});
export default theme
I have imported my theme into my App.js file which is my top level file, I will include that here just in case something has been done wrong with that:
import React,{useState} from "react";
import PicOfDay from "./Components/PictureOfDay";
import Navigation from "./Components/Navigation";
import {
Typography,
} from "#mui/material";
import {ThemeProvider} from '#mui/material/styles'
import theme from "../src/ui/Theme";
import {BrowserRouter as Router} from "react-router-dom";
function App(props) {
const [date, setDate] = useState(new Date());
return (
<ThemeProvider theme={theme}>
<Router>
<Navigation date={date} setDate={setDate} />
<Typography
variant="h1"
style={{fontSize: "5rem", textAlign: "center", marginTop:"2rem"}}
>
Astronomy Picture of the Day
</Typography>
{/* <PicOfDay date={date} /> */}
</Router>
</ThemeProvider>
);
}
export default App;
I did look at some documentation a couple of you sent me, and I was looking at the troubleshooting part where it said "[Types] Property "palette", "spacing" does not exist on type 'DefaultTheme'" because makeStyles is exported differently and it does not know about Theme. There seems to be a snipet to put in a typescript project (which I am not running, I am using javascript) and there was a section to add a ts file to my javascript and put the snippet it recommended, which I tried, but am I missing something because it did not do anything and I am not sure if I need to put something in my App.js file in order for it to read that?
You can still use the makeStyles utils as what you're using, but in material v5 if you love to do it you need to install one more package #mui/styles and
import { makeStyles } from '#mui/styles';
https://mui.com/guides/migration-v4/#mui-material-styles
The makeStyles JSS utility is no longer exported from #mui/material/styles. You can use #mui/styles/makeStyles instead.
Also, you need to add tab and purple to createTheme if you need them
const theme = createTheme({
typography: {
tab: {
fontSize: 20,
},
},
palette: {
common: {
purple: 'purple',
},
},
})
Based on documentation:
#mui/styles is the legacy styling solution for MUI. It is deprecated in v5. It depends on JSS as a styling solution, which is not used in the #mui/material anymore.
You can use the-sx-prop or styled
so what i understood from this question is that you want to add custom classes to the material-ui components. and makestyles is giving you error about theme.. you can resolve this by providing default theme to makestyles. you can use ThemeProvider to do that.. all you've to do is create a default theme with createTheme() then use that in ThemeProvider to pass it to all components in tree below ThemeProvider.. just use ThemeProvider to wrap your root component and that will provide default theme to each makeStyles that are currently in use..
import { makeStyles } from '#mui/styles';
import { createTheme, ThemeProvider } from '#mui/material/styles';
const theme = createTheme();
const useStyles = makeStyles((theme) => (
root : {
background: theme.palette.primary.main,
}));
function Component() {
const classes = useStyles();
return <div className={classes.root} />
}
// In the root of your app
function App(props) {
return <ThemeProvider theme={theme}><Component {...props} /></ThemeProvider>;
}
import * as React from 'react';
import { StyledEngineProvider } from '#mui/material/styles';
export default function GlobalCssPriority() {
return (
<StyledEngineProvider injectFirst>
{/* Your component tree. Now you can override MUI's styles. */}
</StyledEngineProvider>
);
}
You need to use provider on main file to get default styles first.
Visit here Material UI injections!

Invalid prop `className` of type `object` supplied to `Card`, expected `string`

I'm currently working on a React web app using Material-UI. I've been experimenting with the Card component to see how it works. I am currently running the following code:
import React from 'react';
import Card from '#material-ui/core/Card';
import CardMedia from '#material-ui/core/CardMedia';
const useStyles = {
media: {
height: 0,
},
cardWidth: {
maxWidth: 345,
},
cardBounds: {
paddingLeft: '10px',
paddingRight: '10px',
paddingTop: '10px',
paddingBottom: '10px',
}
};
export default function ByteCard(props) {
const classes = useStyles;
return(
<div className= {classes.cardBounds}>
<Card className={classes.cardWidth}>
<CardMedia
className={classes.media}
image={props.byte.image}
title={props.byte.name}
/>
{props.byte.name}
</Card>
</div>
);
}
It's some pretty simple code for sure. However, when running this on Chrome, I get the following two error messages in the inspection console:
It seems really odd to me that the className for the div is not throwing errors but the className for the Card and CardMedia are throwing red flags. I don't see what I'm doing wrong as I think I'm using the className tag the way Material-UI is using it in their examples. Any constructive input whatsoever would be awesome as well!
Use Material-UI style hooks makeStyles
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
media: {
height: 0,
},
cardWidth: {
maxWidth: 345,
},
cardBounds: {
paddingLeft: '10px',
paddingRight: '10px',
paddingTop: '10px',
paddingBottom: '10px',
}
}));
const classes = useStyles();
<Card className={classes.cardWidth}>
You have to use the makeStyles hook like this:
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
yourStyle: {...}
});
export default () => {
const classes = useStyles();
return <Button className={classes.yourStyle}>Hook</Button>;
}

Material ui update select style globally with theme

I am trying to use the following to update the border color of all of my outlined select, but it doesn't work (apparently the style of the border comes from fieldset element). I have tried MuiOutlinedInput but that applies tom all of the inputs. Is there a way to target just the select outlined variant?
overrides: {
MuiButton: {
outlined: {
'&:hover': {
boxShadow: 'none'
},
},
contained: {
'&:hover': {
boxShadow: 'none'
},
}
},
MuiSelect: {
root: {
'& $notchedOutline': {
borderColor: 'red',
},
}
}
}
The problem with what you tried is that the $notchedOutline element is not a descendant of the .MuiSelect-root element, but rather a sibling. The overall structure of the outlined select is roughly as follows (with less relevant details left out):
<div class="MuiFormControl-root">
<div class="MuiOutlinedInput-root">
<div class="MuiSelect-root MuiSelect-outlined MuiOutlinedInput-input">Displayed Text</div>
<input type="hidden" value="Displayed Text">
<fieldset class="MuiOutlinedInput-notchedOutline"><legend>less relevant details</legend></fieldset>
</div>
</div>
Below is an example that customizes both outlined input and outlined select using different colors.
import React from "react";
import ReactDOM from "react-dom";
import TextField from "#material-ui/core/TextField";
import MenuItem from "#material-ui/core/MenuItem";
import { createMuiTheme, MuiThemeProvider } from "#material-ui/core/styles";
const theme = createMuiTheme({
overrides: {
MuiOutlinedInput: {
root: {
"& $notchedOutline": {
borderColor: "pink"
},
"&$focused $notchedOutline": {
borderColor: "red"
},
color: "blue",
"& .MuiSelect-root ~ $notchedOutline": {
borderColor: "green"
},
"&$focused .MuiSelect-root ~ $notchedOutline": {
borderColor: "orange"
},
"& .MuiSelect-root": {
color: "purple"
}
}
}
}
});
function App() {
return (
<MuiThemeProvider theme={theme}>
<TextField
variant="outlined"
label="Outlined Input"
defaultValue="My Text"
/>
<br />
<br />
<TextField
variant="outlined"
label="Outlined Select"
select
value="My Text 1"
>
<MenuItem value="My Text 1">My Text 1</MenuItem>
<MenuItem value="My Text 2">My Text 2</MenuItem>
</TextField>
</MuiThemeProvider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Related answers and documentation:
https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator
Global outlined override
Change outline for OutlinedInput with React material-ui
Can't change border color of Material-UI OutlinedInput
To target the Select component style using the theme of Mui v5`:
import { createTheme } from '#mui/material/styles';
export const theme = createTheme({
components: {
MuiSelect: {
defaultProps: {
variant: 'standard',
},
styleOverrides: {
}
},
}
})
Assuming prior knowledge of how to apply a theme: <ThemeProvider theme={theme}>

How to override (overwrite) classes and styles in material-ui (React)

I'm using version 1.2.1 of material-ui and I'm trying to override the AppBar component to be transparent. The documentation outlines how to override styles here.
My code:
import React, { Component } from 'react';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import logo from '../Assets/logo.svg';
class NavigationBar extends Component {
render() {
const styles = {
root: {
backgroundColor: 'transparent',
boxShadow: 'none',
},
};
return (
<AppBar position={this.props.position} classes={{ root: styles.root }}>
<Toolbar>
<img src={logo} style={{ height: '28px' }} />
</Toolbar>
</AppBar>
);
}
}
export default NavigationBar;
But this yields no results. Am I trying to override wrong? Not sure where I'm going wrong here...
This answer makes #Nadun answer complete - he deserves the credit.
To override material ui classes we need to understand these things:
1. Add your styles in a const variable at the top
const styles = {
root: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
2. We need to use higher order function with "withStyles" to override material ui classes
export default withStyles(styles)(NavigationBar);
3. Now these styles are available to us as props in the render function
try doing this - console.log(this.props.classes) - you get a classes name correspoding to properties you include in styles object,
like - {root: "Instructions-root-101"}.
Add that with classes attribute
render() {
const { classes } = this.props;
return (
<AppBar classes={{ root: classes.root }}>
// Add other code here
</AppBar>
)
}
import React, { Component } from 'react';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import logo from '../Assets/logo.svg';
import { withStyles } from '#material-ui/core/styles';
const styles = {
transparentBar: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
class NavigationBar extends Component {
render() {
return (
<AppBar className={classes.transparentBar}>
<Toolbar>
<img src={logo} style={{ height: '28px' }} />
</Toolbar>
</AppBar>
);
}
}
export default withStyles(styles)(NavigationBar);
find the important part as :
backgroundColor: 'transparent !important'
refer this guide for more details: https://material-ui.com/customization/overrides/
hope this will help you
Adding to above answers, if you want to add style to some internal autogenerated element, you can do this using this syntax
<TextField className={classes.txtField}
then in the classes object, we can approach the label present inside TextField via this way
const useStyles = makeStyles((theme) => ({
txtField: {
"& label": {
padding: 23
}
}
});
import ...;
import { withStyles } from '#mui/styles';
const styles = {
transparentBar: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
function NavigationBar (props) {
const { classes } = props;
return (
<AppBar className={classes.transparentBar}>
<Toolbar>
<img src={logo} style={{ height: '28px' }} />
</Toolbar>
</AppBar>
);
}
export default withStyles(styles)(NavigationBar);
It works for me.
note! update MUI core version

Categories

Resources