React don't apply CSS rule - css

I'm using React to create some button and CSS to styling theme.
So I've created a class Button:
export default class Button extends React.Component{
public className: string;
constructor(props){
super(props);
this.className = props.className ? props.className : "";
}
public render() {
return (
<button className = {this.className}>
{this.value}
</button>
);
}
}
This is my CSS:
.my-css {
width: 300px;
height: 200px;
border-radius: 8px;
}
And this is how I use it:
<Button className = "my-css" value = "Test" />
Why in the inspector I don't see my rule loaded?
Thanks for whoever will answer me! :-)

You should directly refer to your props in you render function :
export default class Button extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<button className={this.props.className}>
{this.props.value}
</button>
);
}
}

Did you loaded the css file. I think you forgot to include css file. You can do so in your main index file by writing import 'path to your css file'.
If you did load the css you can update your code following.
enter code here
export default class Button extends React.Component {
constructor(props) {
super(props);
}
public render() {
const { class = '', value = ''} = this.props;
return (
<button className={class}>
{value}
</button>
);
}
}

Solution 1:
You can create an object in your class and affect the CSS to it like this
const myCss = {
'width': '300px',
'height': '200px',
'borderRaduis': '8px'
};
and affect this object to your button tag like this
<button style={myCss} />
Solution 2
Create your CSS style in a CSS file
Import the CSS file inside your JS file import classes from 'your-file-location.css'
style your button with you class <button className={classes.my-css} />

Related

Is there a way to keep linked stylesheets localized to single components?

I have a component that relies on external stylesheets. I'm bringing the stylesheet into the component like this:
Child component
export default class Child extends Component {
render() {
return (
<div>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />
...my code here...
</div>
);
}
}
But what's happening is this is forcing those styles onto the parent component as well.
Parent Component
export default class Parent extends Component {
render() {
return (
<div>
...code here...
<Child />
... more code here...
</div>
);
}
}
Is anyone aware of a way that I can keep that stylesheet link localized to just that child component so the styles aren't applied to the parent component as well?
Edit 2
Currently trying the shadow dom route, trying to pass down some children. Getting an error after the initial render saying Cannot read properties of undefined (reading 'children'). It does render the this.props.children initially...
import React, { Component } from 'react';
class MyComponent extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
${this.props.children}
`;
}
};
export default class Child extends Component {
render() {
return (
<div>
<script>
{!customElements.get("my-component") && customElements.define('my-component', MyComponent)}
</script>
<my-component>
<h1>Hello from shadow</h1>
</my-component>
<h1>Hello</h1>
</div>
);
}
}
You can try CSS Modules. Add :local(.className) to the class you want to use in your code which is in the font-awesome-min.css file. Then import the styles to your component. For example import styles from './font-awesome-min.css' then use the module in your code. The styles will only apply to specific element and won't affect other elements in the document. So let's say you have a class called .usericon in your css you do this in the css file.
CSS
:local(.usericon){
fill: red;
}
React Code
import styles from './font-awesome-min.css'
export default function Profile(){
return (
<i className={styles.usericon}>User Icon</i>
)
}
One way to truly isolate your CSS is with Web Components. Web Components are a browser API that allows defining custom elements with their own "shadow DOM". If a style is defined inside the shadow DOM, it is truly sandboxed with no styles going in or out. You can use whatever selectors you like:
class FancyBox extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
.fancy-box {
border: solid 3px darkblue;
background: dodgerblue;
padding: 10px;
color: white;
font: 16px sans-serif;
}
</style>
<div class="fancy-box">
<slot></slot>
</div>
`;
}
}
customElements.define('fancy-box', FancyBox);
.fancy-box {
border: dashed 3px darkred !important;
background: crimson !important;
padding: 10px !important;
color: white !important;
font: 16px sans-serif;
}
<fancy-box>Safe in my shadow DOM</fancy-box>
<div class="fancy-box">I am affected by outside stylesheets</div>
Note the use of <slot></slot>. This is a placeholder for child elements of the component.
If I wanted to use this custom element from React, it needs to be defined separately so it only runs once.
class FancyBox extends HTMLElement { /*...*/ };
customElements.define('fancy-box', FancyBox);
class ReactFancyBox extends React.Component {
constructor() {
super();
this.state = { value: 'hello world!' }
}
handleChange(e) {
this.setState({ value: e.currentTarget.value });
}
render() {
return (
<div>
<fancy-box>
<strong>{this.state.value}</strong>
</fancy-box>
<input value={this.state.value} onChange={e => this.handleChange(e)} />
</div>
);
}
};

Change background-color of component depending on where i call it

I've got a problem I can't seem to solve.
I use a component several times in my app but I'd like the background to be different.
I've declared an empty state for the moment, which I'm using in background-color but I can't define the color the component will have. How can I do this?
Thanks for your help
Here is a little piece of my code :
class Gallery extends React.Component {
constructor(props) {
super(props)
this.state = {
activeGal: [],
width: 1920,
teamGal: {},
isOpen: false,
photoIndex: 0,
bgColor: ''
}
}
render() {
const {activeGal, width, teamGal, isOpen, photoIndex, bgColor} = this.state
.gallery {
background-color: ${bgColor};
padding-bottom: 55px;
}
The easiest (and not recommended) way is to use the style prop:
class Gallery extends React.Component {
render() {
const { backgroundColor } = this.props;
return <div style={{ width: "100%", height: "100%", backgroundColor }} />;
}
}
const App = () => {
return (
<div style={{ height: "50vh", width: "50vw" }}>
<Gallery backgroundColor="blue" />
</div>
);
};
More popular solutions are using CSS-in-JS (like styled-components) or CSS variables (See CSS Variables for React Devs).

React modal is not showing in the center of the screen

With the help of the community, I have been able to final have my modal pop-up working on my reat website.
The modal code is as below:
import React from "react";
import '../../assets/styles/GenericTheme.css'
import { Modal, Button } from "react-bootstrap";
class LoginRegisterModal extends React.Component {
constructor(props, context) {
super(props);
this.state = {show: false};
}
open = () => {
this.setState({show: true});
}
close = () => {
this.setState({show: false});
}
componentDidUpdate(prevProps) {
const { show } = this.props;
if (prevProps.show !== show) {
if (show) {
this.open(); // open if parent says to
} else {
this.close(); // close if parent says to
}
}
}
render() {
const styleModal = {
width:770,
height:480,
backgroundColor:"#ffffffff",
borderRadius:21.5,
boxShadow: "0px 8px 18px 0 rgba(0,0,0,0.14)",
}
return (
<Modal show={this.state.show} style={styleModal} >
<Modal.Body>test</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.close}>
Close
</Button>
</Modal.Footer>
</Modal>
);
}
}
export default LoginRegisterModal;
The modal is called by the react-bootstrap Navs components:
const menuLoginRegister = <Nav.Link ref="LoginRegisterModal" eventKey={1} href="#" onClick={this.openLogin}>{TextContents.MenuLoginRegister}</Nav.Link>;
And I have added the modal in the return function like below:
return (
<div>
<Navbar className="village-header" width="100" expand="lg">
....
</Navbar>
<LoginRegisterModal show={this.state.showLogin}
onHide={() => this.setState({ showLogin: false })}/>
</div>
);
The only issues is that the modal keep being displayed on the top left corner and not centered in the screen.
I tried to use a center in the style but it still not move it to the center.
Any idea how to do it ?
Thanks

PrimeReact and styled-component

I can't seem to style a PrimeReact component with styled-component.
Given the below code to render an InputText, my intention is to change the width of it. But it doesn't work.
import styled from "styled-components";
import {InputText} from 'primereact/components/inputtext/InputText';
class Component extends React.Component {
render() {
return (
<InputText/>
)
}
const ComponentView = styled(Component)`
.ui-inputtext {
width: 1000px;
}
`;
styled-components generates a className that should be passed to the component.
import styled from "styled-components";
import {InputText} from 'primereact/components/inputtext/InputText';
class Component extends React.Component {
render() {
return (
<InputText className={this.props.className} /> <---- here
)
}
const ComponentView = styled(Component)`
.ui-inputtext {
width: 1000px;
}
`;
If InputText doesn't accept className, you can simply wrap it with another component:
import styled from "styled-components";
import {InputText} from 'primereact/components/inputtext/InputText';
class Component extends React.Component {
render() {
return (
<div className={this.props.className}> <---- here
<InputText />
</div>
)
}
const ComponentView = styled(Component)`
.ui-inputtext {
width: 1000px;
}
`;
PrimeReact has a lot of styles applied with a separate sass stylesheet, often combining multiple classnames and html tags.
To get your styles to win, you need more CSS specificity.
A solution is to use a nested selector, like:
const ComponentView = styled(Component)`
&&& {
width: 1000px;
}`
This will generate 3 identical classnames and is recommended by the Styled Components docs. More classname specificity needed? Use more &s.
Or you could put in a !important. I've seen this around.
Or edit their sass file.

Add a State property to an Inline Style in React

I have a react element that has an inline style like this: (Shortened version)
<div className='progress-bar'
role='progressbar'
style={{width: '30%'}}>
</div>
I want to replace the width with a property from my state, although I'm not quite sure how to do it.
I tried:
<div className='progress-bar'
role='progressbar'
style={{{width: this.state.percentage}}}>
</div>
Is this even possible?
You can do it like this
style={ { width: `${ this.state.percentage }%` } }
Example
yes its possible check below
class App extends React.Component {
constructor(props){
super(props)
this.state = {
width:30; //default
};
}
render(){
//when state changes the width changes
const style = {
width: this.state.width
}
return(
<div>
//when button is clicked the style value of width increases
<button onClick={() => this.setState({width + 1})}></button>
<div className='progress-bar'
role='progressbar'
style={style}>
</div>
</div>
);
}
:-)

Resources