create-react-app 中的条件 css

IT技术 css reactjs create-react-app
2021-04-03 03:17:07

我有默认的 css 文件和单独的 css 文件,只有在满足某些条件时才应该应用(以 owerride 默认)。

我正在使用具有默认import 'file.css'语法的create-react-app

决定是否动态加载特定 css 文件的最佳方法是什么?

4个回答

require方法仅在开发中有效(因为所有 CSS 都在构建时捆绑在一起),而该import方法根本不起作用(使用 CRA 3.3 版)。

在我们的例子中,我们有多个不能捆绑的主题 - 所以我们使用React.lazyand解决了这个问题React.Suspense

我们有ThemeSelector,它有条件地加载正确的 css。

import React from 'react';

/**
 * The theme components only imports it's theme CSS-file. These components are lazy
 * loaded, to enable "code splitting" (in order to avoid the themes being bundled together)
 */
const Theme1 = React.lazy(() => import('./Theme1'));
const Theme2 = React.lazy(() => import('./Theme2'));

const ThemeSelector: React.FC = ({ children }) => (
  <>
    {/* Conditionally render theme, based on the current client context */}
    <React.Suspense fallback={() => null}>
      {shouldRenderTheme1 && <Theme1 />}
      {shouldRenderTheme2 && <Theme2 />}
    </React.Suspense>
    {/* Render children immediately! */}
    {children}
  </>
);

export default ThemeSelector;

Theme组件的唯一工作是导入正确的 css 文件:

import * as React from 'react';

// 👇 Only important line - as this component should be lazy-loaded,
//    to enable code - splitting for this CSS.
import 'theme1.css';

const Theme1: React.FC = () => <></>;

export default Theme1;

ThemeSelector应包裹App分量,在src/index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import ThemeSelector from 'themes/ThemeSelector';

ReactDOM.render(
  <ThemeSelector>
    <App />
  </ThemeSelector>,
  document.getElementById('root')
);

据我了解,这迫使每个Theme都被拆分成单独的包(实际上也拆分了 CSS)。


正如评论中提到的,这个解决方案没有提供切换主题运行时的简单方法。此解决方案侧重于将主题拆分为单独的包。

如果您已经将主题拆分为单独的 CSS 文件,并且您想交换主题运行时,您可能需要查看使用的解决方案ReactHelmet(如下面@Alexander Ladonin 的回答所示

加载后,似乎没有办法卸载打包的 CSS,是吗?换句话说,我无法创建一个在没有重新加载整页的情况下在浅色/深色主题之间切换的开关。
2021-05-26 03:17:07
我不太确定这是一个解决方案。它仅适用于初始负载。使用此方法初始渲染后无法更改主题。这是因为一旦加载了“Suspense”,它就不能被修改,除非使用上下文挂钩(结果不稳定,相信我,我试过)。另一种选择是在主题更改时强制重新加载
2021-06-01 03:17:07
我们必须将一些 JSX 传递给fallbackprop(至少对于 React 16.12),而不是函数。nullor <div />(当然,在那种情况下更有用的东西。很好的例子!
2021-06-05 03:17:07
这绝对是我找到的最好的解决方案,谢谢先生
2021-06-18 03:17:07

您可以改用require('file.css')语法。这将允许您将其放入条件中。

例如

if(someCondition) {
    require('file.css');
}
@MartinsUntals 是的……如果您使用的是 ExtractTextPlugin,就会发生这种情况。你可以使用 CSS module并定位你的特定组件,这样 CSS 是否在每个页面上都没有关系,或者你可以看看这个——我还没有尝试过,但它可能更接近你想要什么。
2021-05-23 03:17:07
我确实使用了 react html 注入策略。从长远来看还不够好
2021-05-25 03:17:07
谢谢!当我觉得必须存在一个简单的解决方案时,我一直在避免与 webpack 搏斗!由于过度处理这个问题,我的大脑现在再次冷静下来。
2021-05-26 03:17:07
@MartinsUntals 所以你能在部署/生产级别找到动态 CSS 的解决方案吗?
2021-06-04 03:17:07
唔。看起来它只能在开发模式下工作 - 部署后,服务器似乎无论如何都加载了 css,即使从未执行过特定的代码块。毕竟可能在页面加载之前发生了 css 组装:/
2021-06-15 03:17:07

使用react头盔动态地将链接、元标记等添加到文档标题中将其添加到任何渲染方法中。

import {Component} from 'react';
import ReactHelmet from 'react-helmet';

class Example extends Component{
    render(
        <ReactHelmet link={
            [{"rel": "stylesheet", type:"text/css", "href": "/style.css"}]
        }/>);
    }
}

您可以在下一次<ReactHelmet/>渲染时重写它

其他解决方案对我不起作用。经过一天的搜索,我获得了以下解决方案。在我的问题中,我有两个用于 RTL 或 LTR 的 CSS 文件,例如app.rtl.cssapp.ltr.css

Style像这样创建一个功能组件

import React, { useState } from "react";

export default function Style(props) {
  const [stylePath, setStylePath] = useState(props.path);

  return (
    <div>
      <link rel="stylesheet" type="text/css" href={stylePath} />
    </div>
  );
}

然后你可以调用它,例如App.js

function App() {
...
return (    
  <Style path={`/css/app.${direction}.css`} />
)}

directionparam 包含rtlltr确定应该加载哪个文件。