css modules in react - javascript

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

Related

Navbar.module.css usage

I am very new to this react stuff. I tried to add styling to my navbar component from module CSS file but it is showing me an error where style can only have objects, not strings.
Below is my code for react component.
I have first imported the file :
import styles from './Components/Navbar.module.css'
Then i tried to give the styles to my component div :
<div className='navbar' style = {styles.navbar}>
I would appreciate your help!
Everything has been mentioned above. Please Help!
Here you are assigning a className as string, rather assign the {styles.navbar} to className and remove the style attribute. This is because the {styles.navbar} is a string and it will assign the component styles as per the className. This will fix your code.
<div className={styles.navbar}>

Is it possible to load stylesheets for React component by extension when env is specified?

I've read a bit about <ThemeProvider />, React.lazy, React Helmet, and a few others but they don't seem to do what I would like; unless they do and I'm looking at their uses incorrectly or am using the wrong terms to search and research - if so, please let me know as it would be very helpful to have someone go "These are what you want to use, you just need to continue working with them to get it".
I have a website with shared components that have two stylesheets each containing color and sizing variables, one for Light and one for Dark. Ideally, I want the shared components to determine when to load the respective Light and Dark styles without needing to place conditional within each and every component, ie:
import lightStyle from 'div.module.scss';
import darkStyle from 'div.dark.module.scss';
...
<div className={ApplicationVariableService.isDarkMode() ? darkStyle.div : lightStyle.div}>
<p className={ApplicationVariableService.isDarkMode() ? darkStyle.p: lightStyle.p}>
{children}
</p>
</div>
...
rather I want to apply className={styles} to all the elements.
I got close with the following:
import React from 'react';
let styles;
if (ApplicationsVariableService.isDarkMode()){
import("./div.dark.module.scss")
.then((res) => {
styles = res;
});
} else {
import("./div.module.scss")
.then((res) => {
styles = res;
});
}
...
return(
<div className={styles}>{children}</div>
)
The downside is that this block would need to be added to each and every component not only replicating the same thing over and over but should additional stylesheets come in later all of these blocks will need to be modified.
I'm thinking I could import then export all of the component stylesheets into a light_index.js and dark_index.js then add the if/else to the main index.js file that exports all of the components for use in the App. That could potentially hit load speed because I don't want to load all of the component stylesheets, just the stylesheets for the component rendering on the page.
My current file structure:
// shared components
src
stylesheets
_light_variables.scss
_dark_variables.scss
components
div
div.jsx
div.module.scss // imports light_variables
div.dark.module.scss // imports dark_variables
index.js
// App
app
src
components
page.jsx
index.js
Maybe I'm over thinking it? Can I have this file structure and the desired behavior without loading both light and dark stylesheets for every component? I am thinking about the future where more stylesheet might be added later and I wouldn't want to have to edit every components conditional import statement or the condition rendering in each and every element. Was I looking in the right direction with <ThemeProvider /> and React.lazy?
Guidance would be much appreciated!
Update: I completely redid my approach as explained in my other question. For edification and anyone else wanting to do something similar, if you have a solution please share it!

How to prevent style tags of unused React components

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.

What is the best way to style a component explicitly?

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

Workaround to add className to Fragment in React

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

Categories

Resources