Best way to import .module.scss classes in react? - reactjs

I'm working on a NextJs project and I've seen 2 ways of importing css classes from a .module.scss file.
Option 1:
import * as styles from './page.module.scss';
Classes used like this:
<div className={styles.myClass} />
Option 2:
import {myClass} from './page.module.scss';
Classes used like this:
<div className={myClass} />
I've always used option 2, as it looks much cleaner to just write the class name in the render instead of having loads of 'styles.' everywhere.
However i've come to learn that option 2 does not work with storybook for some reason? In order to get it to work, I have to write this as a workaround:
import styles from './page.module.scss';
const { myClass } = styles;
So i'm wondering, what is the difference between the 2 on a functional level?

On a code basis, there is no difference between the two. Both involve destructuring the objects during importation.

Related

class name convention in react material-ui framework

Is there a class name convention used in material ui library? I'm currently using material-ui-next. I notice class names like "MuiFormControl-root-124" all over the place with numbers appended to class name. For Paper element "MuiPaper-root-18 MuiPaper-shadow2-22 MuiPaper-rounded-19". I just can't see a pattern here.
Is there a convention which I'm missing. It would be easier to understand this framework if it made sense like Bootstraps grid classes. All help much appreciated. Thank you.
In material-ui v1, class names are non-deterministically generated at run time, so there is no convention you should adhere to. That's described here in the docs:
You may have noticed that the class names generated by our styling solution are non-deterministic, so you can't rely on them to stay the same.
However, that does not matter because you should never be using raw CSS class names in the first place. Instead, you use withStyles to set the appropriate styles for each component:
import { withStyles } from 'material-ui/styles';
// Define the CSS styles you which to apply to your component
const styles = {
root: {
backgroundColor: 'red',
},
};
class MyComponent extends React.Component {
render () {
// withStyles automatically provides the classes prop, which
// will contain the generated CSS class name that you can match
// to your component
return <div className={this.props.classes.root} />;
}
}
export default withStyles(styles)(MyComponent);
These non-deterministic class names have technical benefits, including improved performance:
Thanks to the non-deterministic nature of our class names, we can implement optimizations for development and production. They are easy to debug in development and as short as possible in production.
You should note that this happens because material-ui takes a fundamentally different approach to styling than a library like Bootstrap. While Bootstrap has a CSS library with defined class names that get applied to each element, material-ui uses CSS in JS to inject styling. This allows CSS to be defined and stored alongside the JavaScript definition of each component.

Avoiding a long list of imports in React

For a SET game that I am creating in React (using Create React App), I need to import 81 image files representing the 81 possible cards used in the game. With the help of a Python script, I created this extremely long list of imports
import i0000 from './assets/0000.png'
import i0001 from './assets/0001.png'
[...]
import i2221 from './assets/2221.png'
import i2222 from './assets/2222.png'
and since I will need to reference those variables using strings representing each card, I have this object:
const refs = {
'0000': i0000,
'0001': i0001,
[...]
'2220': i2220,
'2221': i2221,
'2222': i2222
};
The good thing is that now I have all the card images pre-loaded to be called easily with
<img src={refs[card]} />
But the bad thing is I have 164 lines of ridiculous code that make it work. I'm wondering if there is a better way to pre-cache and reference a directory full of images.
Move all the images to your public folder, say public/cards.
Then you can reference them with <img src={`cards/${card}.png`} /> without the need for any import statement.
Webpack can no longer warn you if the referenced images are missing though, so just make sure they are there.
Two approaches:
First, you eliminate manually creating the refs object by struturing your code like this:
export i0000 from './assets/0000.png'
export i0001 from './assets/0001.png'
And where you want to use these assets:
imports * as refs from './assets'
<img src={refs[card]} />
Secondly, you could use a bundling system that supports dynamic requires e.g. https://webpack.github.io/docs/context.html#dynamic-requires

Import default react component with two or more different name

What I am trying to do:
Import the same default component twice or more times in one file. The reason of why I want to do this are because the component are the same, I only need the name difference to make it more readable.
What I have done:
import ToInput from './input';
import FromInput from './input';
Is there a correct way to do this? It works, but the ESLint is complaining about duplicate import.
import Input as MyInput from './input';
import Input as MySecondInput from './input';
Now you may use the component as MyInput or MySecondInput, as both are references or instances of the same component.
You shouldn't ever need to do this. Post the scenario as to why you need this.
Just do this:
const FromInput = ToInput;
Or just disable the eslint rule for that file if you really need it.
/* eslint-disable import/your-rule-here */
It seems like what you really want to do is create two distinct instances of an Input component, but what you have described is to create a copy of the Input component class/descriptor. While it is possible to do this, it is usually a bad practice.
Try to think about React in terms of Object Oriented concepts. Remember that the imported construct from './input' (in your case, ToInput) is a Class and not yet an Instance of that class.
Traditionally to create an instance of a class called Input, we would write something like this:
var toInput = new Input()
However, when defining an instance of the class Input in React, we typically use JSX tags:
<Input />
The above is JSX tag is an instance of Input, and NOT actually the Input class itself.
From what I gather in your question, I think the following would be a more appropriate approach that employs better patterns and practices.
Import a singular, generic Input component descriptor/class.
import Input from './input'
If readability is your ultimate goal, then perhaps differentiate the two components with a prop, rather than creating copies of the component class. You could use an id prop for example:
<Input id='to-input' />
<Input id='from-input' />
Hopefully this answers your question.

Keep classnames with CSS loader or organize code in React?

How can I use my own class names when using CSS and Style loaders? I'm using React and i often get confused with all the class names and the related components. If it is not recommended to keep the class names, how can I organize my code in a manner that it don't get messy?
You can use normal classNames and then import the relative .css file that has the style for those classes. Something like this:
MyComponent.js
...
import '/path/to/css/style.css'
...
render() {
return(<div className="MyComponent">Hello</div>);
}
...
style.css
...
.MyComponent {
width: 100px;
background-color: red;
...
}
...
And this would work just fine, with this approach though you are in charge of naming your classes and making sure there are no collisions and everything is named properly (you can then follow BEM techinque or others as you prefer).
Otherwise there are other approaches that I am not gonna explain into details because the relative docs are great and don't need any addition.
You can use Css Modules or Styled Components. There is also this article that has a good overview of these methods and can help you out make a final decision.

How to import a component or file in React using variables?

I'm building a web app using React that shows the blueprint for the building you select, in an already selected campus.
I have a "Content" component that loads the campus or building map, depending what you chose.
The "BuildingMap" component needs to load a specific blueprint according to what building you selected. It gets the props.building with the name of the building but I don't know how to load a component using that variable.
I have tried import, fetch and require but nothing seems to work.
Please help.
My code looks something like this:
//Content Component
<BuildingMap building={selectedBuilding} campus={selectedCampus} />
//BuildingMap Component
import *MyBlueprint* from (specific folder depending on the campus selected)
class BuildingMap extends React.Component {
render(){
return (
<div className="blueprint" id={this.props.building}>
{*MyBlueprint*}
</div>
)
}
}
Unfortunately, you cannot import/require components dynamically in React environment.
Depending on how many buildings/blueprints there are, it's possible to import them one by one, create component-building map and pick component by building ID.
If there are many/infinite components to load, I would surely pick another method - don't know content of your problem.
import BlueprintA from './BlueprintA'
import BlueprintB from './BlueprintB'
import BlueprintC from './BlueprintC'
// ...
class BuildingMap extends React.Component {
render(){
const C = {
buildingA: BlueprintA,
buildingB: BlueprintB,
buildingC: BlueprintC,
// ...
}[this.props.building]
return (
<div className="blueprint" id={this.props.building}>
<C />
</div>
)
}
}
This question is pretty old but as I was looking for how to solve the same problem let me give my answer. It can be done with dynamic import React.lazy:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
See more details here: https://reactjs.org/docs/code-splitting.html#reactlazy
To add to #Andreyco's answer:
Using a lookup table of string IDs/names to component classes is a typical React idiom. One common use case is a modal manager component that can render multiple different types of modals. For some examples, see Dan Abramov's answer at "How can I render a modal dialog in Redux?" (not Redux-specific), as well as some of the related articles in the React Component Patterns#Modal Dialogs and Redux Techniques#UI sections of my React/Redux links list.
Per #azium's comment: it is definitely possible to use dynamic importing (via require.ensure() or the new import() function) to load chunks at runtime, and you could add the exports from those dynamically imported chunks into a lookup table when they are loaded.

Resources