How to remove imported css in reactjs
Asked Answered
N

2

10

I have used the following code to import css

componentWillMount() {
    import('./patient-summary.css');
}

How to remove imported css from react when component is not in use. When i go back to previous screen this css gets applied there. Any idea ?

UPDATE:: Webpack config

const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: './src/index.js',
  output: {
  filename: 'bundle.js',
  path: path.resolve(__dirname, 'public/dist')
},
module: {
  rules: [
      {
          test: /\.js?$/, 
          loader: 'babel-loader',
          exclude: /node_modules/
      },
      {
          test: /\.css$/,
          use: [ 'style-loader', 'css-loader' ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        loader: "file-loader"
      }
      ,
      {
        test: /\.(png|jpeg|jpg|gif|svg)$/,
        loader: "file-loader"
      }
  ]
  },
  devServer: {
  contentBase: path.resolve(__dirname, "public"),
  historyApiFallback: true,
  port: 3000,
  watchOptions: {
    // Delay the rebuild after the first change
    aggregateTimeout: 300,

    // Poll using interval (in ms, accepts boolean too)
    poll: 1000,
  },
  },
  plugins: [
   // Ignore node_modules so CPU usage with poll
   // watching drops significantly.
   new webpack.WatchIgnorePlugin([
      path.join(__dirname, "node_modules")
   ])
 ],
 };
Nuggar answered 1/1, 2018 at 5:32 Comment(7)
Please post your webpack configurations. I think you concat all css files together.Jaynes
why would you want to remove the imports. they will be in the local cache. let it be thereDud
@M.R.Safari updatedNuggar
So... I guess you haven't found any solution yetEngaged
@Engaged I found it. To import all css files at top of the component. Atlast in webpack build all the css into a single file. So its not individual css files. Just one fileNuggar
But that's not a solution to your question is it? To remove imported css. You are still loading everythingEngaged
There is no way to remove an imported css. You can override with !important, or switch the entire HTML fileNuggar
A
6

I found a (sort of) reasonable way to do this in React. In short, you can lazy-load React components that contain the import './style.css', and when it loads, you can capture the imported StyleSheet to toggle its StyleSheet.disabled property later.

Here's the main code, with more explanation below. Here's my Gist.

useDisableImportedStyles.tsx

import { useEffect } from 'react'

// global list of all the StyleSheets that are touched in useDisableImportedStyles
const switchableGlobalStyleSheets: StyleSheet[] = []

// just to clarify what createUseDisableImportedStyles() returns
type useDisableImportedStyles = () => void

export const createUseDisableImportedStyles = (
    immediatelyUnloadStyle: boolean = true
    // if true: immediately unloads the StyleSheet when the component is unmounted
    // if false: waits to unloads the StyleSheet until another instance of useDisableImportedStyles is called.This avoids a flash of unstyled content
): useDisableImportedStyles => {
    let localStyleSheet: StyleSheet
    return () => {
        useEffect(() => {

            // if there are no stylesheets, you did something wrong...
            if (document.styleSheets.length < 1) return

            // set the localStyleSheet if this is the first time this instance of this useEffect is called
            if (localStyleSheet == null) {
                localStyleSheet = document.styleSheets[document.styleSheets.length - 1]
                switchableGlobalStyleSheets.push(localStyleSheet)
            }

            // if we are switching StyleSheets, disable all switchableGlobalStyleSheets
            if (!immediatelyUnloadStyle) {
                switchableGlobalStyleSheets.forEach(styleSheet => styleSheet.disabled = true)
            }

            // enable our StyleSheet!
            localStyleSheet.disabled = false

            // if we are NOT switching StyleSheets, disable this StyleSheet when the component is unmounted
            if (immediatelyUnloadStyle) return () => {
                if (localStyleSheet != null) localStyleSheet.disabled = true
            }

        })
    }
}

WARNING: This is pretty finicky. You must set this up exactly or there may be unintended consequences

Conditions:

  1. createUseDisableImportedStyles must called in global scope in the same tsx file as the imported css being targeted and the component to be lazy loaded
import React from 'react'
import { createUseDisableImportedStyles } from './useDisableImportedStyles'
import './global-styles.css'
const useDisableImportedStyles = createUseDisableImportedStyles()
export const CssComponent: React.FC<{}> = () => {
    useDisableImportedStyles()
    return null
}
export default CssComponent
  1. A component using this hook should be lazy loaded:
LazyCssComponent = React.lazy(() => import('./cssComponent'))
...
<React.Suspense fallback={<></>}>
    {condition && <LazyCssComponent/>}
</React.Suspense>
  1. An exception to lazy loading might be using this in a single, normal, non-lazy component so styles are loaded on first render
  • NOTE: the InitialCssComponent never needs to actually render, it just needs to be imported
  • BUT: this will only work if there is one single .css file imported globally, otherwise, I don't know what would happen
import InitialCssComponent  from './initialCssComponent'
LazyCssComponent = React.lazy(() => import('./cssComponent'))
//...
{false && <InitialCssComponent/>}
<React.Suspense fallback={<></>}>
    {condition && <LazyCssComponent/>}
</React.Suspense>

GOOD LUCK!

Attenuator answered 2/5, 2021 at 0:38 Comment(1)
Works like a charm. I had to add a loop to select the first truly local stylesheet though, some google font import kept creeping to the end of document.styleSheets.Kulseth
F
1

First of all, AFAIK, you should not call any imports in componentWillMount. This means that every time a new component about to mount, this css will be loaded over and over. Instead, it must be placed at the beginning of your module.

The way that you avoid unnecessary css imports is to avoid unnecessary component imports. Hence, if your component is not called anywhere, then this css will not be loaded.

For routing, I think you will need to do some code splitting, but I am not sure if it is straightforward or the right way to do.

Link 1 Link 2

Figueroa answered 1/1, 2018 at 6:5 Comment(4)
How do we avoid importing modules since we want to routeNuggar
I think you will need to do some code splitting, but I am not sure if it is straightforward or the right way to do. I added two links.Figueroa
Thanks for the info . I have divided the code. But if once the css is added, if i go back to previous screen, its affected with css added later onwardsNuggar
This is incorrect. Imports in ES6 (and webpack) are only loaded once. You can verify this yourself in the inspector. If there are multiple selectors, they will appear in the styles panel crossed out.Ultimo

© 2022 - 2024 — McMap. All rights reserved.