How to use SCSS variables into my React components - reactjs

I am working on a React project that follows this structure
src |
components |
Footer |
index.jsx
styles.scss
Header |
index.jsx
styles.scss
scss |
helpers.scss
variables.scss
...
main.scss
Into my variables file I was using the css custom variables so, all them where on :root and I can access them in my components styles.
When I wanted to create the dark colours I wanted to use the SCSS function darken, but it does not evaluate them and throws an error saying that var(--blue) is not a valid colour.
As a solution I decided to move all the variables into a SCSS variables but when project is building it throws another error that says that a $blue is not defined.
The unique solution possible I can use, it is to include the variables file in all the styles files but, I do not know if there are a better solution for the structure that I am using.

From React 17
To access your scss variables into the react component, you need to do something like that
Install node-sass as a dependency or dev dependency
No need to do any config change in webpack
import as a module <-- main point
variables.module.scss
$color: skyblue;
$primaryColor: red;
:export {
color: $color;
primary-color: $primaryColor;
}
App.js
import variables from '<YOUR_PATH>/variables.module.scss';
const App = () => {
console.log(variables);
}

If you don't want to use styled-component
then you can follow this link.
https://til.hashrocket.com/posts/sxbrscjuqu-share-scss-variables-with-javascript

I use a similar structure to organize my .scss files. I like having the styles in the same folder as the component. However, I import all scss files to my main.scss file. This helps avoid style conflicts in the DOM.
main.scss
import "./scss/helpers.scss"
import "./variables.scss"
import "./Footer/style.scss"
import "./Header/styles.scss"
Make sure to name your files with an underscore so that all the files get merged on compilation. Note you don't need to name the underscore in the import.
_helpers.scss
_variable.scss
_style.scss
Using this method you only need to import styles once into your app. index.jsx

There are different ways I can recomend you to tackle this.
1- Duplicate the values of those variables. Add them both on your variables.scss and as constants in some other file, maybe config.js or constants.js that way you'll be able to reference these values from your react components, the downside to this, is you'll have to remember to change them in two places if you have to modify the value.
2- Consider using styled-components. With styled components you can define your styles within your components, using variables or props within the styles.
3- Use some mechanism to define these variables in a single file or as environment variables, and setup your build process to be able to import these values into js and scss files.

It is possible to use custom variables with that project structure using css-vars mixin.
After proposing the option to evaluate custom variables before executing the SCSS function, a guy suggested me this mixin. I have just tested and works pretty nice.

Related

How to import SCSS on Component Level with Next.js

I am coming from a CRA background and working my way through Next.js version 9.4.2
My project tree looks something like this :-
pages/
_app.tsx
index.tsx
components/
Navbar/
index.ts
Navbar.tsx
Navbar.scss
Inside my Navbar.tsx I have a statement import './Navbar.scss';
This gives me the following error :-
./src/components/Navbar/Navbar.scss
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to src/pages/_app.tsx.
Read more: https://err.sh/next.js/css-global
Location: src/components/Navbar/Navbar.tsx
The error, as mentioned, goes away if I move the import Navbar.scss statement to pages/_app.tsx
I know I can switch to Navbar.module.scss, but I don't want to go down the route of modular scss as I expect my scss to get complex I would like to stick to the manner in which I write my scss and not keep finding work arounds to issues that might arise later. I am open to being convinced here but I have not found good read ups on this to choose it as my path.
So by the looks if it, I am stuck with importing all <component>.scss files in _app.tsx. This will leave me with a long list of <component>.scss imports in my _app.tsx and I will also be left with a lot of <component>.scss files for Components that might conditionally not render.
What are my options here ?
Your Navbar.scss file is not named properly.
Let's say your stylesheet contains something like...
$color: red;
.someclassselector {
color: $color;
}
Component stylesheet files have to be named in the following convention for next.js to compile them as addressed in next's css getting started guide
<TheComponent>.module.scss
be imported like this:
import styles from './<MyComponent>.module.scss>';
and be applied to the component like this:
<TheComponent className={styles.someclassselector} />
Not really an expert but it seems that you should stick to class selectors as global selectors can only be declared if you import them in pages/_app.js. You may name a main.scss file to use Global or Tag Element selectors like h1 {},h2{}, * {}, etc.

ReactJS mixed all css

First page is Index.js and contains Index.css
Path-> /src/action/Index.js
- src
|
-- action
|
--- Index.js
import '../css/Index.css';
Second page is Customer.js contains Auth.css
Path-> /src/action/User/Customer.js
- src
|
-- action
|
--- User
|
---- Customer.js
import '../../css/Auth.css';
The problem is that both pages are using both CSS files. How can I avoid this?
Those CSS files become global when imported like that. The easiest way is to add classNames to your component like this:
<ComponentA className="a">
Then in corresponding CSS file target the class:
.a {
color: red;
}
In reality you might want to get to know CSS-in-JS solutions like styled-components or learn automatic hashing for CSS with webpack. Check this tutorial for example: https://blog.bitsrc.io/5-ways-to-style-react-components-in-2019-30f1ccc2b5b
Your index.css module should import a "tree" of relevant css modules, using #import "example.css".
I'd recomment to nest it more, to different css modules that import other css themselves, creating a logical tree of css imports.
Using that, the only import you'll need to do is to the root index css.

Import TypeScript variable in React

I am trying to style (styled-components) a fabric js component (Dropdown) as a react component.
The css class names are declared in a file office-ui-fabric-react/lib/components/Dropdown/Dropdown.scss.d.ts. Example:
export declare const root = "root_15a7b352";
I want to import this class name so I can use it in styled.
AFAIK this is TypeScript global variable and I tried looking for information on how to get to it but with no success.
The statement declare const root is not the same as const root. It means:
There is a variable called root somewhere else, and I'm just here to describe it.
In other words, it tells us something on the type level, but it doesn't contain any executable code. It's not possible to consume it in runtime. You can verify it by inspecting the generated code in TypeScript playground.
Most likely it's meant to be imported from someplace else, or is, in fact, a global variable Since the declaration file describes Dropdown.scss, it's likely that root is a CSS class living in that file. Try:
import { root } from 'office-ui-fabric-react/lib/components/Dropdown/Dropdown.scss'
Karol Majeswski's Answer gets it right on importing the variable from typescript.
However, it seems your intention is to style parts of the dropdown using styled-components, instead of importing this variable from scss file, the Dropdown component provides readable classnames like ms-Dropdown-title that can be used for styling.
For eg. to style the Dropdown, you would use:
const StyledDropdown = styled(Dropdown)`
color: red;
& .ms-Dropdown-title {
background-color: red;
}
`;
See Codepen example

React How to generate a separate stylesheet for a specific component?

Here I want to generate a separate stylesheet for Landing component and hopefully for other. Other components will have Hero component too. Can anyone tell me how can I do that?. Is it a good idea?.
Anything with an underscore _name.scss, tells your sass compiler that it's a partial scss file. Simply don't use an underscore for single component scss files, for example: Hero.scss. Then in your Hero.js, you can import the style like so:
import './Hero.scss';
<div className="heroContainer">...</div>
or, if your webpack has been configured to allow scss module imports, then you could do:
import { heroContainer } from './Hero.scss';
<div className={heroContainer}>...</div>
If you want to share heroContainer's styles with other stylesheets, simply use the #extend in your scss file.
clientsContainer {
#extend .heroContainer;
}
The downside to this approach is that you'll have to manually import any partials, like _vars.scss, _mixins.scss...etc, and any other dependent stylesheets into each new Example.scss file.
Ideally, if you're working in a large team, it's better to individualize your scss stylesheets, so that everything is modular (components and their styles can be passed off to someone else, instead of having to send ALL of your stylesheets for ONE component).

Why do I have to use "require" instead of "import from" for an image in React?

I see that this answer suggests the syntax for importing images as shown below (commented out). In my case, it didn't work out (complaining there's no modules to find in that file) and I had to switch to the syntax that's currently active.
// import Author from "../assets/author.png";
var Author = require("../assets/author.png");
The difference I can imagine is that I'm using TypeScript (transpiling my TSX by awesome-typescript-loader and loading my PNG file-loader) and they seem to use JSX. But as far my understanding goes, it all transpiles to plain JS and require in the end.
Being a noob on React, I'm not sure what the reason of this discrepancy is but also I'm not sure what to google for to investigate myself.
This is more of a problem with typescript than webpack itself, you might need to declare modules on a declaration file.
Create a declarations.d.ts
Update your tsconfig.json
"include": [
"./declarations.d.ts",
],
Put this on that file:
declare module '*.png';
Error might be gone.
You can declare a module for your images like this:
declare module "*.png" {
const value: any;
export default value;
}
Then, you will be able to import your image like this:
import AuthorSrc from "../assets/author.png";
This is happening because webpack doesn't support image import out of the box. So you need to add a rule for that in the webpack config file. When you add a new rule, TypeScript doesn't automatically know that, so you need to declare a new module to resolve this. Without the module, you will be able to import images, but TypeScript will throw an error because you didn't tell to it is possible.
This issue has nothing to do with webpack or any bundler and is not quite a problem with typescript.
Typescript has stated that `require("path") is a way to include modules to the scope of your current module, whilst it can be also used to read some random files (such as json files, for example).
As Vincent and Playma256 specified, you can declare a module wildcard to match certain file types, so you can import it as an import statement. But you don't really need to do this. Typescript won't give you an error if you are trying to import a png or a json file (tslint might, but that depends on your configuration).
By the way, if your declaration is within the source folder of your project as defined in tsconfig.json, you don't need to include it as specified by Playma256.
I've created a sample project in node for you to test:
https://github.com/rodrigoelp/typescript-declare-files
I think you can solve this problem with Webpack&&typescript.The official webpage of webpack has introduced something about this in
https://webpack.js.org/guides/typescript/
And I have try this myself in
https://github.com/reactpersopnal/webpack-root/tree/feature/typescript
The reason is that you would like to use non-code assets with TypeScript, so we need to defer the type for these imports for webpack.
Your could simply add custom.d.ts.
declare module "*.jpg" {
const content: any;
export default content;
}

Resources