React CSS class gets override automatically on production server - javascript

I am facing a weird CSS issue in my React project. A particular part of the JSX <div> has a class applied to it and added some style properties in the main .css file of the project. In local development, everything works fine but as soon as the build is created and uploaded to the production server, that particular part of the JSX <div> CSS class changes and the styling gets distorted.
Example:
Original JSX
import React, { useEffect, useState, useContext } from "react";
import Tooltip from "#material-ui/core/Tooltip";
import { withStyles, makeStyles } from "#material-ui/core/styles";
import Slider from "#material-ui/core/Slider";
const useStyles = makeStyles((theme) => ({
root: {
width: 450,
},
margin: {
height: 100,
},
}));
const PrettoSlider = withStyles({
root: {
color: "red",
height: 8,
},
thumb: {
height: 24,
width: 24,
backgroundColor: "#fff",
border: "2px solid currentColor",
marginTop: -8,
marginLeft: -12,
"&:focus,&:hover,&$active": {
boxShadow: "inherit",
border: "2px solid #fff407 !important",
},
},
active: {
backgroundColor: "#fff407",
},
})(Slider);
const CustomizedSlider = ({
id,
abbr,
type,
minElig,
maxElig,
}) => {
useEffect(() => {
setValue(sliderPreviousValue);
}, [sliderPreviousValue]);
const classes = useStyles();
return (
<>
<div className={classes.root}>
{type === "intervention" ? (
<ProgressBar max={maxElig} value={sliderValue} />
) : null}
{renderSlider}
</div>
</>
);
};
Original DOM:
<div class="diabMetr clearfix">
<span class="diabLabl">Diabetes</span>
<div class="makeStyles-root-1">
<span class="MuiSlider-root WithStyles(ForwardRef(Slider))-root-3 MuiSlider-colorPrimary"><span class="MuiSlider-rail WithStyles(ForwardRef(Slider))-rail-8"></span><span class="MuiSlider-track WithStyles(ForwardRef(Slider))-track-7" style="left: 0%; width: 83.3333%;"></span><input type="hidden" value="200"><span class="MuiSlider-thumb WithStyles(ForwardRef(Slider))-thumb-4 MuiSlider-thumbColorPrimary PrivateValueLabel-open-12 PrivateValueLabel-thumb-11" tabindex="0" role="slider" data-index="0" aria-label="pretto slider" aria-orientation="horizontal" aria-valuemax="240" aria-valuemin="0" aria-valuenow="200" style="left: 83.3333%;"><span class="PrivateValueLabel-offset-13 MuiSlider-valueLabel WithStyles(ForwardRef(Slider))-valueLabel-6"><span class="PrivateValueLabel-circle-14"><span class="PrivateValueLabel-label-15">200</span></span></span></span></span>
<div class="valueOuter clearfix"><label class="valueLeft">0</label><label class="valueRight">240</label></div>
</div>
</div>
The CSS for this JSX is:
.diabMetr {
padding-top: 10px;
span.diabLabl {
display: inline-block;
width: 200px;
text-align: left;
font-size: 12px;
line-height: 30px;
text-align: right;
#include respond-to(media-xl) {
width: 120px;
}
}
span.MuiSlider-root {
width: 100%;
padding: 0;
height: 0px;
.MuiSlider-rail {
height: 30px;
border-radius: 15px;
background: #e8e8e8;
opacity: 1;
}
.MuiSlider-track {
height: 30px;
background: #88d479;
border-radius: 15px;
}
.MuiSlider-thumb {
z-index: 12;
width: 35px;
height: 35px;
border-radius: 50%;
margin-left: -17px;
border: #88d479 solid 2px;
margin-top: -3px;
}
.MuiSlider-markLabel.MuiSlider-markLabelActive:last-child() {
right: 0 !important;
}
}
}
.makeStyles-root-1 {
width: calc(100% - 220px) !important;
float: right;
margin-top: -22px;
}
The DOM changes after build and uploaded to the server:
<div class="diabMetr clearfix">
<span class="diabLabl">Diabetes</span>
<div class="jss16">
<span class="MuiSlider-root jss18 MuiSlider-colorPrimary"><span class="MuiSlider-rail jss23"></span><span class="MuiSlider-track jss22" style="left: 0%; width: 83.3333%;"></span><input type="hidden" value="200"><span class="MuiSlider-thumb jss19 MuiSlider-thumbColorPrimary jss27 jss26" tabindex="0" role="slider" data-index="0" aria-label="pretto slider" aria-orientation="horizontal" aria-valuemax="240" aria-valuemin="0" aria-valuenow="200" style="left: 83.3333%;"><span class="jss28 MuiSlider-valueLabel jss21"><span class="jss29"><span class="jss30">200</span></span></span></span></span>
<div class="valueOuter clearfix"><label class="valueLeft">0</label><label class="valueRight">240</label></div>
</div>
</div>
The CSS for the class .jss16 is:
.jss16 {
width: 450px;
}
Issue to notice
Only the class .makeStyles-root-1 gets replaced with some random class .jss16 when the build gets uploaded to the server and the CSS changes accordingly, the rest of the JSX remains unchanged. I tried searching for the class .jss16 everywhere in the code, but it's not found. Also, everything works fine on localhost.
I tried adding the CSS properties to the .jss16 like this:
.jss16 {
width: 450px;
width: calc(100% - 220px) !important;
margin-top: -22px;
float: right;
}
and then re-initiate the uploading process but then instead of .jss16, another class is replaced something like .jss42. This keeps on repeating and does not work on any new build created.
I also tried the following CSS:
.diabMetr + span + div {
width: 450px;
width: calc(100% - 220px) !important;
margin-top: -22px;
float: right;
},
but this also didn't help. The styling of the app still remains distorted (incorrect, not as on localhost).
I spent several hours searching for this but in vain. If anyone can assist me in understanding this error and resolve the same, will be highly appreciated. Thanks in advance!

there are quite a few issues with this code. First in jsx CSS class is given as className as #Max has mentioned in his/her answer.
Another issue is that #material-ui's makeStyle doesn't work in this way. The classNames inside the makeStyle change to random names in the build stage. This happens to keep the classNames uniques, this is #material-ui's feature. I'd suggest you to read this #matrial-ui's documentation about makeStyles. And here a code example is provided.
To use makeStyles classes you've to hook it into your component.
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
root: {
backgroundColor: 'red',
color: props => props.color,
},
});
export default function MyComponent(props) {
const classes = useStyles(props);
return (
<div className={classes.root}>
Lorem iosum poder
</div>
);
}
Update
According to your jsx code, add the styles which you've added in css class .makeStyles-root-1 in the useStyles object. It'll add the styles to the element.
After adding those CSS styles in useStyles this object will look like this:-
const useStyles = makeStyles((theme) => ({
root: {
width: 'calc(100% - 220px) !important',
float: 'right',
marginTop: '-22px'
},
margin: {
height: 100,
},
}));
The root class will contain those styles and it'll be applied without providing the styles separately from the CSS file.

Solution
I am not sure what component creates the div with "jss16" class, assume it is ExternalComponent.
You should add a custom className (assuming ExternalComponent handles this correctly):
<ExternalComponent className="myclass">
...
</ExternalComponent>
this will create a DOM like this:
<div class="jss16 myclass">
...
</div>
Sou you can create css for myclass:
.myclass {
width: calc(100% - 220px) !important;
float: right;
margin-top: -22px;
}
Explanation
ExternalComponent uses jss to dynamically generate css classes, so you cant rely on the name of the dynamically generated class. In most of the cases, components with custom classes should append props.className to the generated jss like this:
return (
<div className={jssClassname + props.className ? ' ' + props.className : ''}>
{children}
</div>
);

I couldn't reproduce the error because I had some syntax issues, so I wonder if fixing these, the build will behave correctly:
Add closing / to input
Write style's using objects, example style={{left: '0%', width: '83.3333%'}}
Update class to className
Update tabindex to tabIndex
Lastly, if that doesn't help, to make your CSS work, ie .diabMetr + span + div, rewrite it to:
.diabMetr > span + div {}
or
.diabMetr > div {}
Right now, it's not selecting the child element.

Related

onDoubleClick is not working on react to call a function

I'm following this React tutorial here: https://ibaslogic.com/how-to-edit-todos-items-in-react/ to build a simple TO DO app.
I've also reviewed Why onDoubleClick event is not working in React.js? but there's no onclick event to worry about in my example.
My onDoubleClick event should call a function handleEditing but nothing happens when I double click a list item.
I'm unsure of why it does not work (the web browser does not seem to register a double click event.
Below is my example:
import React from "react";
import styles from "./TodoItem.module.css";
class TodoItem extends React.Component {
state = {
editing: false,
};
handleEditing = () => {
console.log("doubleClick")
this.setState({
editing: true,
});
};
render() {
const completedStyle = {
fontStyle: "italic",
color: "#595959",
opacity: 0.4,
textDecoration: "line-through",
};
const { completed, id, title } = this.props.todo;
let viewMode = {}
let editMode = {}
if (this.state.editing) {
viewMode.display = "none"
} else {
editMode.display = "none"
}
return (
<li className={styles.item}>
<div onDoubleClick={this.handleEditing} style={viewMode}>
<input
type="checkbox"
className={styles.checkbox}
checked={completed}
onChange={() => this.props.handleChangeProps(id)}
/>
<button onClick={() => this.props.deleteTodoProps(id)}>Delete</button>
<span style={completed ? completedStyle : null}>{title}</span>
</div>
<input type="text" style={editMode} className={styles.textInput} />
</li>
);
}
}
export default TodoItem;
I don't think this is relevant, but here is my css:
.item {
font-size: 1.2rem;
list-style-type: none;
padding: 17px 0px;
border-bottom: 1px solid #eaeaea;
}
.checkbox {
margin-right: 15px;
}
.item button {
font-size: 13px;
background: #f1f3f4;
border: none;
cursor: pointer;
float: right;
outline: none;
border-radius: 100px;
height: 50px;
width: 50px;
margin: -10px 0 0 10px;
}
.textInput {
width: 100%;
padding: 10px;
border: 1px solid #dfdfdf;
}
onDoubleClick works when your dev tool is not opened
Updated answer:
As found out in the comments, the problem was a combination of OS and Browser. Windows / Chrome in this example.
Old answer:
I haven't read into much detail, but the first difference I can spot is that in your code the handleEditing is not bound. Which should not prevent the output of your console.log. Does it appear?
onDoubleClick={this.handleEditing.bind(this)}
Hope this helps in your case.

Can't style with SASS/SCSS in React properly

Take this SCSS stylesheet:
#import "../vars";
img.userIcon {
&.regular {
max-width: 64px;
max-height: 64px;
}
&.small {
max-width: 32px;
max-height: 32px;
}
border-radius: 50%;
border: 2px solid $bg-light;
}
How on earth do I get my page to recognise the .regular or .small?
This my UserIcon.tsx that applies this styling:
import styles from "../styles/components/UserIcon.module.scss";
type Props = {
src: string,
variant?: "regular" | "small"
}
export default function UserIcon({ src, variant = "regular" }: Props) {
return <img className={`${styles.userIcon} ${variant} mb-2`} src={src} />
}
Now, this obviously won't work because somewhere along the lines, the class names are all jumbled up and look like this:
<img class="UserIcon_userIcon__1jFAP regular mb-2">
Which is odd, because it doesn't ever do this to the boostrap scss files that I have imported.
So I need to know either:
How to remove the class name renaming.
How to implement .regular and .small properly, such that it uses the jumbled up name.
pass variant as key argument to your styles object:
return <img className={`${styles.userIcon} ${styles[variant]} mb-2`} src={src} />
Can you try something like that.
#import "../vars";
img.userIcon {
border-radius: 50%;
border: 2px solid $bg-light;
}
img.regular {
max-width: 64px;
max-height: 64px;
}
img.small {
max-width: 32px;
max-height: 32px;
}
import styles from "../styles/components/UserIcon.module.scss";
type Props = {
src: string,
variant?: "regular" | "small"
}
export default function UserIcon({ src, variant = "regular" }: Props) {
return <img className={`${styles.userIcon} ${styles[variant]} mb-2`} src={src} />
}
Tell me if it solved your problem

Change styles of component when hovering sibling

I have a simple case where I want the box2 to change background to yellow, if the box1 was hovered.
code sample:
const Box = styled.div`
height: 200px;
width: 200px;
background: blue;
`;
const Box2 = styled.div`
height: 200px;
width: 200px;
background: green;
margin-top: 20px;
${Box}:hover {
background: yellow;
}
`;
in render:
<Box>Box 1</Box>
<Box2>Box 2</Box2>
Link to the code preview:
https://stackblitz.com/edit/react-rvhgov
Thanks!
Edit This one above doesnt seem to work, dont know why, it should work?
Depend on your render items you can do it with different approaches but as things we got here, you can use adjacent sibling combinator (+) or general sibling combinator (~). So all you have to do is to replace this
${Box}:hover {
background: yellow;
}
with
/* If you want to only select the next element sibling, you should replace ~ with + */
${Box}:hover ~ & {
background: yellow
}
Working Demo:
https://stackblitz.com/edit/select-next-sibling
You can try this:
import React, { Component, useState } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import styled, {css} from 'styled-components';
const Box = styled.div`
height: 200px;
width: 200px;
background: blue;
`;
const Box2 = styled.div`
height: 200px;
width: 200px;
background: green;
margin-top: 20px;
${props => props.hovered && css`
background: yellow;
`}
`;
export default function App() {
const [hovered, setHovered] = useState(false);
return (
<div className="App">
{'' + hovered}
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Box onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}>Box 1</Box>
<Box2 hovered={hovered}>Box 2</Box2>
</div>
);
}
render(<App />, document.getElementById('root'));
With this approach, it doesn't matter are elements/components siblings or not. It will work for siblings but also when components are nested in different subtrees.

How can I extend the header to the full page width? [duplicate]

This question already has an answer here:
How to extend header to the full page width? [duplicate]
(1 answer)
Closed 3 years ago.
How can I extend my header to the full page? I have tried margin-left & right but that doesn't work.
Header.css
.header{
background: green;
height: 70px;
width: 100%;
display: flex;
justify-content: space-between;
margin-bottom: 25px;
left: 0;
right: 0;
}
.header-right {
float: right;
}
#media screen and (max-width: 500px) {
.header-right {
float: none;
}
}
Here's my app.tsx file:
const Header = () => (
<div className = 'header'>
<h1>Instaride</h1>
<div className="header-right">
<Button> Sign In</Button>
<Button> Contact</Button>
</div>
</div>
);
export default Header;
I have already tried this too:
body, html{
margin:0;
padding:0;
}
Just add document.body.style.margin = 0; in your component.
Here is your component with MUI way of styling,
import React from "react";
import { makeStyles } from "#material-ui/styles";
import { Button } from "#material-ui/core";
const useStyles = makeStyles({
header: {
background: "green",
height: "70px",
width: "100%",
display: "flex",
justifyContent: "space-between",
marginBottom: "25px",
left: "0",
right: "0"
},
headerRight: {
float: "right",
color: "blue"
}
});
export default function Header() {
document.body.style.margin = 0;
const classes = useStyles();
return (
<div className={classes.header}>
<h1>Instaride</h1>
<div className={classes.headerRight}>
<Button> Sign In</Button>
<Button> Contact</Button>
</div>
</div>
);
}
I've also created sandbox for you: https://codesandbox.io/s/serene-sun-n5rth?fontsize=14&hidenavigation=1&theme=dark
It works perfectly alright for me with whatever code that you have shared - https://react-xukh1h.stackblitz.io
May be you have included some css themes or library which might be intruding whatever that you are trying to achieve.

How to add props in react for styles?

I have a simple section in which I want to change the width dynamically
Here is section
<div className="form-control">
<Formats>
{styles.map(style => <ButtonStyled type="button" active={style.id === styleId} onClick={() => setStyleId(style.id)} key={`button-${style.name}`}>{style.name}</ButtonStyled>)}
{activeStyle && <FormatsContent>
<FormatsDescription>{activeStyle.desciption}</FormatsDescription>
<Proportions>
{activeStyle.proportions.map(x => <Proportion onClick={() => setProportion(x.proportion)} active={proportion === x.proportion} width={x.width} height={x.height} key={`proportion-${x.proportion}`}>{x.proportionLabel}</Proportion>)}
</Proportions>
</FormatsContent>}
</Formats>
</div>
Here is style
const Formats = styled.div`
margin-left: 0px;
padding:12px;
background-color: ${gray.brightest};
border-radius: 20px;
width: 100%;
& select {
height: 31px;
padding: 0;
margin-left: 12px;
}
`;
Now I want to add props to check if width is full or not isFullWidth:true/false
and on styles to use it like this,
const Formats = styled.div`
margin-left: 0px;
padding:12px;
background-color: ${gray.brightest};
border-radius: 20px;
width: ${props => props.isFullWidth ? '100%' : '59%'}
& select {
height: 31px;
padding: 0;
margin-left: 12px;
}
`;
What do I need to change to achieve what I want?
The Format component should have isFullWidth prop holding either true or false as value as shown below:
The example below will give a 100% width
<Format isFullWidth ={true}>
</Format>
And this one will give a 59% width
<Format isFullWidth ={false}>
</Format>
I think it is enough to pass the prop to the component and keep the last style you posted:
So it should be
<Formats isFullWidth>
...
</Formats>
EDIT: wrong prop name

Categories