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')) * ... * }> * {condition && } * * ``` * - 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 && } * }> * {condition && } * * ``` * * @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 !