unable to use styles from local css file - reactjs

I am creating reactjs web app where I am trying to use styles from a local css file. Source code is given for reference.
/src/css/aboutcompany.css
.center {
text-align: center;
color: red;
}
/src/AboutCompany.js
import React,{Component} from 'react';
import style from './css/aboutcompany.css';
class AboutCompany extends Component{
render(){
return(
<div>
<p className="style.center"> Company</p>
<hr/>
Technologies is leading Company providing end to end software solutions to customers globally. We are specialized in every vertical of industries and deliver quality solutions using latest technologies.
</div>
)
}
}
export default AboutCompany;
webpack.config.js
var config = {
entry: './src/index.js',
output: {
path:'/build/',
filename: 'index.js',
},
devServer: {
inline: true,
port: 8081,
historyApiFallback: true
},
module: {
rules: [
{
test: /\.(jpg|png|svg)$/,
use: 'url-loader'
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /\.css$/,
use: 'css-loader'
}
]
}
}
module.exports = config;
As you can see in the AboutCompany.js here <p className="style.center"> Company</p> we are trying to use css class center , but it does not work. Can someone tell me where am I wrong.

To make use of css modules in development first you need to install style-loader:
$ npm install style-loader --save-dev
then in your configurations pass modules=true as an option to css-loader
{
test: /\.css$/,
use: ['style-loader', 'css-loader?modules=true']
}
finally in your jsx code you can call your classes like this:
<p className={styles.center}/>
and you are done.

Related

Style sheet is not styling React Component

I searched for similar problems a lot but couldn't come up with a solution.
I integrated React.js with my working project. I am using Webpack.
Everything runs properly except styling.
I have Style.scss and I import this file in my react file. It compiles without an error but the actual style is not applying to the element.
The inline style works and other classes that are included normally also are fine.
Style.scss
.wtf {
font-weight: bold;
font-size: 40px;
}
Test.js
import React from 'react';
import '../Styles/Style.scss';
const style = {
border: 'solid 5px green'
};
export default class Test extends React.Component {
render() {
return (
<div style={style} className='wtf text-danger'>
Am I React.Component? And I am working too?
</div>
);
};
}
According to the snippet above, text-danger applies color red and border:solid 5px green works too, however, the style is specified in Style.scss is not working.
I checked compiled file and it seems like my scss style code exists there
This is the result in the browser
My webpack.config.js file content is below:
const path = require( 'path' );
module.exports = {
mode: 'development',
entry: {
rooms: './react-src/rooms/rooms.js',
tasks: './react-src/tasks/tasks.js'
},
output: {
filename: '[name].js',
path: path.resolve('../htdocs/react-dist')
},
module: {
rules: [
{
test: /\.scss$/,
use: [
// style-loader
{ loader: 'style-loader' },
// css-loader
{
loader: 'css-loader',
options: {
modules: true
}
},
// sass-loader
{ loader: 'sass-loader' }
]
},
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
]
}
};
Any idea what is the problem?
Solved
According to my example and my Webpack configuration, it was compiling styles so generating a new class name.
So, that huge token highlighted above is my actual class name which I have to use.
It can be imported as an Object so I can access class name as a property.
This is how it worked.
import React from 'react';
import style from '../Styles/Style.scss';
export default class Test extends React.Component {
render() {
return (
<div className={style.wtf}>
Am I React.Component? And I am working too?
</div>
);
};
}
if you modify your webpack config to:
{...
loader: 'css-loader',
options: {
modules: false
},
...}
you can use regular className property

How to add classnames from less with webpack and react?

I have a webpack configuration that uses less-loader, css-loader, and style-loader. When I import less file into my component file, the css is visible in chrome's devTools, but the classname is not.
I have google'd for a couple of hours and can't seem to find anything that can explain this. I know I am suppose to use this.props.className, but I am not sure how the className gets propagated. I have also tried using static strings for the className.
Here is my webpack config:
module: {
rules: [
...
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
]
},
Here is my component:
import React from 'react';
import {AppBar} from '#material-ui/core';
import '../styles/layout.less';
class Home extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<AppBar className='header'></AppBar>
);
}
}
export default Home;
I expect the className to be header, but it doesn't show any class names i provide. It only happens with Material-UI components.
Sorry for late answer, recently had similar problem with 'antd' library and theme modification using less files. I had to split my webpack configuration into two parties (for node_modules and for resources) as follow:
{
test: /\.less$/,
include: /node_modules/,
use: [
{
loader: 'style-loader' // creates style nodes from JS strings
},
{
loader: 'css-loader', // translates CSS into CommonJs
},
{
loader: "less-loader", // compiles Less to CSS
options: {
javascriptEnabled: true
}
}
],
},
{
test: /\.less$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader' // creates style nodes from JS strings
},
{
loader: 'css-loader', // translates CSS into CommonJs
options: {
modules: true
}
},
{
loader: "less-loader", // compiles Less to CSS
options: {
javascriptEnabled: true
}
}
],
}
Hope that helps.

Nested classes not working in CSS Modules with webpack

Im using webpack and css-loader and style-loader to enable css modules in my React app. These are the following setup:
Webpack config:
module.exports = {
mode: "development",
entry: __dirname + "/app/index.js",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true,
localIdentName: "[name]__[local]___[hash:base64:5]"
}
}
]
}
]
},
output: {
filename: "bundle.js",
path: __dirname + "/build"
},
plugins: [HTMLWebpackPluginConfig]
};
And in my React component I've coded this:
import React from "react";
import styles from "./Carousel.css";
class Carousel extends React.Component {
render() {
return (
<div className={styles["carousel"]}>
<img
className={styles["test"]}
src="https://i2.wp.com/beebom.com/wp-content/uploads/2016/01/Reverse-Image-Search-Engines-Apps-And-Its-Uses-2016.jpg?resize=640%2C426"
/>
</div>
);
}
}
export default Carousel;
In my Carousel.css file:
.carousel {
background-color: red;
.test {
width: 200px;
}
}
When I check the rendered HTML, I can see carousel class and its properties coming in the parent div. But the child img tag shows the class name but no property is associated with it.
Any idea what Im doing wrong here?
EDIT:: Sam's suggestions worked and Im summarising the changes that solved it:
Since nesting is a feature of css, we need to use sass or less. And for that I used postcss-loader.
Updated webpack config rules section:
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true,
localIdentName: "[name]__[local]___[hash:base64:5]"
}
},
*"postcss-loader"*
]
}
Also added a postcss.config.js file like this:
module.exports = {
plugins: [
require("postcss-nested")({
/* ...options */
})
]
};
And added postcss-loader, postcss-nested packages using npm install -D option.
How are you importing the css file ?
You can follow the below way to import too,
In your component,
import ‘styles.css’
In HTML element,
<div className='carousel'>
<div className='test'></div>
</div>
In webpack config,
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}

React-Date "SingleDatePicker" not working as expected?

I am using react-dates and trying to implement singledatepicker. All the functionality is working but I dont know why all the default styles are gone. I am also using babel "transform-class-properties"
import React from 'react';
import moment from 'moment'
import 'react-dates/initialize';
import {SingleDatePicker} from 'react-dates';
import 'react-dates/lib/css/_datepicker.css';
const now= moment();
export default class ExpenseForm extends React.Component{
state={
description:'',
note:'',
amount:'',
createdAt:moment(),
calendarFocused:false
}
onDateChange = (createdAt)=>{
this.setState(()=>({createdAt}));
}
onFocusChange =({focused})=>{
this.setState(()=>({calendarFocused:focused}))
}
render(){
return(
<div>
<h3>ExpenseForm</h3>
<form>
<SingleDatePicker
date={this.state.createdAt}
onDateChange={this.onDateChange}
focused={this.state.calendarFocused}
onFocusChange={this.onFocusChange}
/>
</form>
</div>
)
}
}
Here is my Webpack config file and it is loaded with css-loader
const path = require('path');
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},{
test: /\.s?css$/,
use:['style-loader','css-loader','sass-loader']
}
]
},
devtool:'cheap-module-eval-source-map',
devServer:{
contentBase:path.resolve(__dirname, 'public'),
historyApiFallback:true
}
};
I had exact the same problem when integration react-dates into my project, and I believe the root cause is that the css module in your project also compile the css of react-dates which leads to missing of the style. To solve this problem, you could modify the rule in your module like:
...your original css module rule
exclude: [
/node_modules/
]
after applying this rule, you might encounter another issue which is that these css files can't be properly handled due to being excluded, you should then add another css module to handle those css file that you don't want to mess with, for example:
exports.vendorCss = {
test: /\.(css|scss|sass)$/,
include: [/node_modules/],
loaders: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
},
],
};
and there you have it!! Hope this can help!

How can I set a CSS name not to be a hash in a Webpack configuration file?

I just wondering why my CSS name became hash after I build and run my React + Webpack application. Is there advance configuration that I may have missed to set the CSS name as normal?
This is my Webpack configuration:
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: './app/app.jsx',
output: {
path: __dirname,
filename: './public/bundle.js'
},
resolve: {
alias: {
applicationStyles: path.resolve(__dirname,'app/styles/app.css'),
Clock: path.resolve(__dirname,'app/components/Clock.jsx'),
Countdown: path.resolve(__dirname,'app/components/Countdown.jsx'),
CountdownForm: path.resolve(__dirname,'app/components/CountdownForm.jsx')
},
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
},
devtool: 'cheap-module-eval-source-map'
};
This is the CSS name that becomes hash:
To be more clear, I add the source code of how I import and use the CSS on React:
import React from 'react';
import ReactDOM from 'react-dom';
import Countdown from 'Countdown';
/* Import the CSS file */
import Styles from 'applicationStyles';
ReactDOM.render(
/* Use CSS */
<div className={Styles.box}>
<Countdown/>
</div>,
document.getElementById('app')
);
This is what Webpack does by default to avoid identical CSS classes (from different CSS modules) to collide.
Here are three things you can do:
1: At the app level, you can add the following configuration to your Webpack to disable CSS modules. It is not recommended as it could lead to collisions and hard-to-find bugs.
options: {
modules: false
}
2: At the file level, you can import it like this to prevent Webpack from obfuscating the class names. This is useful when importing third-party configuration libraries CSS files.
import '!style!css!golden-layout-css-base';
3: At the CSS class level, you can use :global(.your-class-name) to avoid obfuscating a specific class
:global(.container) {
padding: 10px;
}
In your Webpack configuration, the CSS loader needs a configuration for prefixed names. Basically localIdentName:'[local]' sets the pre-fixer as the local class name only.
For detailed info, you can look at the documentation for CSS Loader
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true,
localIdentName:'[local]'
}
}
]
}
]
}
The class name can be combined with an auto-generated hash using the localIdentName option of CSS Modules by setting it to [local]_[hase:base64:5].
[local] here refers to the class name.
[hash:base64:5] means generate a Base64 hash string of length 5.
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[local]_[hash:base64:5]'
}
}
]
}
By setting the css-loader modules options to an object, you're essentially setting modules to true, but with specific options.
Setting the localIdentName to [local] completely defeats the purpose of using CSS Modules.

Resources