How can we add a style explicitly to a component in react. By explicitly I meant that if we are visiting the component the style should be applied and if we are navigating away from that component the style should be removed.
Scenario 1
Suppose if we have two components day and night and the default background-color of application is is white. Then if I use\visit the night component then the back-ground color should change to black and if I navigate away from the night component the background-color should change back to the default
Solution 1
//night component
import React from "react";
import './style.css' //give background-color: black
and then import other style sheet that has background-color: white property to other components. But this is not ideal as we may end up adding style-sheet to all other components.
You can read this for an overview of the several ways you can style react components, but for your specific case, I would recommend using Styled Components. It's a js library that combines well good-old stylesheets with inline css, and let's you style your components dynamically. You can read the docs and try it for yourself, but in your case, you would be able to have a background property whose value would depend on a prop (day or night for example). Try it out, you won't regret it :)
if there is a fair amount of logic for deciding classes you can use classnames
import classNames from 'classnames';
const BackgroundColor = () => {
const [toggle, setToggle] = useState(true)
// Define css logic
const bgToggle = classNames({
'background-color: black': toggle,
'background-color: white': !toggle'
});
// Toggle state
const setToogle = () => setToggle(!toggle)
return <div onClick={setToogle} className={bgToggle}>{toggle}</div>
}
This is one way of doing it, there are other ways ofc
Related
How can I dynamically change the entire background dynamically for light and dark mode? Redux holds my darkMode state.
For instance, I want the background to be black when on darkMode and white when I'm not on darkMode. How can I dynamically adjust? With an HOC?
Redux (useSelector):
const darkMode = useSelector((state: ReduxState) => state.accountPreferencesReducer.darkMode);
Here's the issue I'm running into when I scroll all the way down (White background):
Typically with light and dark mode people generally use a context provider (https://reactjs.org/docs/context.html) to pass in a global stylised component. A pretty example of how to do this can be seen here: https://www.smashingmagazine.com/2020/04/dark-mode-react-apps-styled-components/
BUT
You can do a hacky way (Not suggested) of stylising your components with darkMode by reading your dark mode state from redux inside every single component that you want to be affected. Then you need to create 2 styles for each of these components and do something like:
const lightStyle = { backgroundColor: "white" };
const darkStyle = { backgroundColor: "black" };
const themeStyle = state.darkMode ? darkStyle : lightStyle;
.
.
<div style = {themeStyle}>
<JSX-components/>
</div>
This is a lot of work, and I suggest you use something similar to a stylised library of components that is easier to use.
I am having some trouble with css modules in react I dont know how to use react modules in a dynamic way
import classnames from 'classnames'
import styles from './hover.module.css
///
///
const [flashElements,setFlashElements]=useState(elementList.map(element => {
return element.classes.flash
}))```
///
///
I want to be able to display the classes showing the value that corresponds to the element in state . is this even possible or should I approach the problem differently
I want to be to do some thing like the code below
return (
<a classname={styles.HOVER ,styles.flashElements[i]}>
Instead of import styles from './hover.module.css' try using import './hover.module.css' in your component and you can directly use the class names from your CSS file.
Use classNameinstead of classnamein your <a> tag
I think this question may expand beyond React, but I'm still not sure if React itself is responsible for the problem.
The environment is React with TypeScript. I use CSS imports in the component files, so that each component has its specific stylesheet and I presume that those styles will not be added to the <head> element until the respective component is instantiated. But it turns out that if I import a component from a file, which just reexports all of them, the styles of all the other components, which I do not use, are still added in the DOM.
Here is a simple example, let's say I have two simple components in the lib folder - Avatar and Button. They look like this (the Button is similar):
import React from 'react';
import './avatar.css';
const Avatar: React.FC = (props: any) => {
return (
<div className="avatar">
{props.children}
</div>
);
}
export { Avatar };
Then I add index.ts to reexport the components, in order to have simple import path:
import { Avatar } from './Avatar';
import { Button } from './Button';
export { Avatar, Button };
And finally, in my AppComponent I want to use only the Button component:
import React from 'react';
import { Button } from './lib';
const App: React.FC = () => {
return (
<div className="App">
<Button>example</Button>
</div >
);
}
export default App;
To my surprise, in the <head> element there are <style> tags not only for the Button, but also for the Avatar. Why is this happening? Is my reexport configuration wrong?
Notice that if I import the component directly from its file - import { Button } from './lib/Button' I do not get the Avatar styles.
The example is really simple, but the real scenario is related to a React component library, which contains a lot of components with a lot of stylesheets. I want to avoid inserting so many <style> tags in the DOM, unless they are really needed.
Thank you for spending time on this!
so that each component has its specific stylesheet and I presume that those styles will not be added to the element until the respective component is instantiated
This presumption is wrong. React uses webpack to bundle its files and the way webpack works for CSS imports is that it loads all the CSS files that your project depends on and put them in the <head> element right at the beginning.
You might ask: Then how do I keep my styles separated and don't get them mixed.
There are three solutions to this
A good way is to Add a CSS Modules Stylesheet
Another suggestion is to make the <div> that wraps your component have a className that is the same name as the component so your component will look like this
export default class ComponentOne extends Component {
...
render() {
return(
<div className="ComponentOne">
...
</div
)
}
}
And your component CSS file will look like:
.ComponentOne div img {
...
}
.ComponentOne .class-one {
...
}
With this way, using CSS preprocessor like SASS will come in handy, so your .scss file will simply begin with:
.ComponentOne {
...
}
Another solution is to have the styles as an object inside your component. This way the style will only be scoped to your component and will be removed when the component unmounts, but then you will lose the ability to easily create #media queries andother special effects like:hover` plus this approach is not recommended for small components that get mounted and unmounted too often because this creates a performance issue once the application gets larger
You also might ask: since all the style sheets get imported at the begging, then why don't I put all my styles in one big style sheet and not splitting them up.
Other than the fact that splitting your styles will make them easy to handle so that each component will have its separate CSS file and webpack will handle importing them, There is one other benefit:
Say you have a feature1 component which also has a feature1.css file. In the beginning, when you have feature1 imported in your main app, webpack will also import its style sheet and put it in the <head> element.
But say in the future you decided you don't want to use feature1 component anymore and you are using another feature2 component now which has its own feature2.css file. Now since no other component is importing feature1 component, webpack will also ignore importing feature1.css into the <head> element.
The switch component Blueprint (demo and documentation here) displays no border when selected/unselected. I included this component in a React component as follows:
import {Component} from "react";
import {Switch} from "#blueprintjs/core";
import React from "react";
class BPrintMain extends Component{
render(){
return (
<Switch id="switch-input-3" label="Public" disabled={false} />
)
}
}
export {BPrintMain};
When I click the switch component, it displays a border as follows:
The border remains until the focus is lost, that is, I click on something else on the page.
I am including the Blueprint css files from the css of my main componeent as follows:
#import "~#blueprintjs/core/lib/css/blueprint.css";
#import "~normalize.css";
#import "~#blueprintjs/icons/lib/css/blueprint-icons.css";
The css appears to be working for buttons, input controls etc. What am I missing? Why is the switch displaying that focus/bounding box on focus?
Ok, I found the answer. Leaving it here in case someone else gets bitten by this and uses my choice of words for expressing the problem.
As explained in this github issue this is expected behaviour of browsers: display the element with focus. As the answer in the issue says, simply adding the following two lines to your app (I did it in index.js, the root of my React app) solves the problem:
import { FocusStyleManager } from "#blueprintjs/core";
FocusStyleManager.onlyShowFocusOnTabs();
I am trying to create a stateless component in React with the sole purpose of acting as a reusable wrapper. I am also using CSS Modules because I want to have fully modular CSS.
The thing is I don't want to add unnecessary elements (and even more so <div>s), but instead I want to use React's Fragments.
Now, the problem I have is Fragment (at least for now) do not accept classNames. So if I try this:
// In Wrapper.js:
import React, { Fragment } from 'react'
import styles from './Wrapper.css'
const wrapper = (props) => (
<Fragment className={styles.wrapper}>
{props.children}
</Fragment>
)
export default wrapper
In (for example) Navbar.js:
import React from 'react'
import styles from './Navbar.css'
import Wrapper from '../../Layout/Wrapper'
const navBar = (props) => (
<nav className={styles.navBar}>
<Wrapper>
This is the site's main navigation bar.
</Wrapper>
</nav>
)
export default navBar
Now I can of course, use a div instead of the Fragment, but is there any other workaround to avoid using unnecessary markup, of which I am totally unaware at this hour of the night? :)
Thanks in advance for any insight, recommendation, correction, or any other form of help!
Fragments let you group a list of children without adding extra nodes to the DOM. - https://reactjs.org/docs/fragments.html
What Fragments tries to solve it's the unnecessary dom elements but this doesn't mean that Fragments will replace div entirely. If you need to add a className there, it's clear that either you add a dom element in this case another div or add the className to its parent.
Using Fragment means not adding an extra node to DOM.
If you want to assign a className to a node then you'll have to use div.
Create a css file and import it inside your App.js
Create a higher order component withClass.js like below
import React from 'react';
const withClass = (WrappedComponent, className) => {
return props => (
<div className={className}>
<WrappedComponent {...props} />
</div>
);
};
export default withClass;
Import your hoc too.
In your App.js write something like below
<React.Fragment>
<p>Some JSX code here</p>
<React.Fragment>
export default withClass(App, classes.App);
I created .App class inside my css file and imported it so that i can use it later with classes.App. This way you can apply any css class that you create inside your css.You can use the same wrapperComponent to wrap every component you have, by simply importing it and changing export in your component. You just have to make classname of your choice and use it in export statement of your component. When you write props with spread operator(...). All the props from your component will be passed to this wrapperComponent.
PS : English is not my native language so I am not good at explaining but this code will do the trick. Would appreciate a moderator taking look into my explanation.
So the only thing the Wrapper / Fragment does is acting as a CSS wrapper over the children of nav?
I am not very experienced with css-modules, but if I wanted to avoid an extra DOM node just for the className I'd use something like this to get both classNames applied to <nav>:
import React from 'react'
import navStyles from './Navbar.css'
import wrapperStyles from './Wrapper.css'
const navBar = (props) => (
<nav className={`${navStyles.navBar} ${wrapperStyles.wrapper}`}>
This is the site's main navigation bar.
</nav>
)
export default navBar