Skip to content

Instantly share code, notes, and snippets.

@arniebradfo
Last active January 29, 2024 14:33
Show Gist options
  • Save arniebradfo/dc1dcb0793108cfc4cfca8faf0cb15d3 to your computer and use it in GitHub Desktop.
Save arniebradfo/dc1dcb0793108cfc4cfca8faf0cb15d3 to your computer and use it in GitHub Desktop.
React Disable Imported Styles
import React from 'react'
LazyCssComponent = React.lazy(() => import('./cssComponent'))
AnotherLazyCssComponent = React.lazy(() => import('./anotherCssComponent'))
export const App: React.FC = () =>(
<React.Suspense fallback={<></>}>
{condition && <LazyCssComponent/>}
{!condition && <AnotherLazyCssComponent/>}
</React.Suspense>
)
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
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
/**
* Conditionally apply imported .css files
* 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
* ```tsx
* 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
* ```
*
* 2. A component using this hook *should* be lazy loaded:
* ```tsx
* LazyCssComponent = React.lazy(() => import('./cssComponent'))
* ...
* <React.Suspense fallback={<></>}>
* {condition && <LazyCssComponent/>}
* </React.Suspense>
* ```
* - 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
* ```tsx
* import InitialCssComponent from './initialCssComponent'
* LazyCssComponent = React.lazy(() => import('./cssComponent'))
* ...
* {false && <InitialCssComponent/>}
* <React.Suspense fallback={<></>}>
* {condition && <LazyCssComponent/>}
* </React.Suspense>
* ```
*
* @param {boolean} immediatelyUnloadStyle
* 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
*
*/
export const createUseDisableImportedStyles = (
immediatelyUnloadStyle: boolean = true
): 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
}
})
}
}
// GOOD LUCK !
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment