【问题标题】:Change props depending on breakpoint with SSR support使用 SSR 支持根据断点更改道具
【发布时间】:2021-05-13 07:33:37
【问题描述】:

我正在使用material-ui@v5,即。 alpha 分支。

目前,我有一个自定义的 Timeline 组件可以执行此操作:

const CustomTimeline = () => {
  const mdDown = useMediaQuery(theme => theme.breakpoints.down("md"));

  return (
    <Timeline position={mdDown ? "right" : "alternate"}>
      {/* some children */}
    </Timeline>
  );
};

它主要按预期工作,但移动用户可能会遇到布局变化,因为useMediaQuery 是使用 JS 实现的,并且仅在客户端。我想寻求与上述代码等效的 CSS 实现以与 SSR 一起使用。

我想到了以下几点:

const CustomTimeline = () => {

  return (
    <Fragment>
      <Timeline sx={{ display: { xs: "block", md: "none" } }} position="right">
        {/* some children */}
      </Timeline>
      <Timeline sx={{ display: { xs: "none", md: "block" } }} position="alternate">
        {/* some children */}
      </Timeline>
    </Fragment>
  );
};

这将起作用,因为 sx 属性被转换为 emotion 样式并嵌入到 HTML 文件中,但这会增加 DOM 大小。有没有更好的方法来实现这一目标?

【问题讨论】:

  • 你不能用 javascript 来做,因为节点环境中没有窗口对象(在 ssr 期间)。所以 CSS 肯定是唯一的选择。
  • 我想你误解了我的问题。我附加的代码 sn-ps 都按预期工作。事实上,第一个正在我的生产站点中使用。我正在寻找的是等效的 CSS 实现,以实现更好的 UX 和 SSR 支持。
  • 是的,我明白了。但我担心第二个代码块是绕过position 绑定(这是javascript)的唯一方法。绑定由 javascript 评估,您可以在其中检查窗口宽度。这只能在客户端渲染期间工作,而不是在服务器端渲染期间。因此,正如您在问题中所述,最好的选择是使用 css-media-query 检查复制元素
  • 虽然另一种选择是找出哪些 css 规则应用于 Timeline 组件的内部 html 元素,但您也希望在 csr 期间向 Timeline 组件添加一个专用的 css 类作为 ssr,并编写包含此 css 的 2 个响应式 css 块(一个用于小时间线,一个用于大时间线)。然后你摆脱了你的 javascript 绑定。​​
  • 您还在寻找答案吗?

标签: javascript reactjs material-ui server-side-rendering breakpoints


【解决方案1】:

我之前也遇到过同样的问题,我使用 Next.js 来处理 SSR。不过没关系。

请先安装这个包并在你的根目录下导入,比如 App.js

import mediaQuery from 'css-mediaquery';

然后,创建这个函数来传递material-ui的ThemeProvider

  const ssrMatchMedia = useCallback(
        (query) => {
            const deviceType = parser(userAgent).device.type || 'desktop';
            return {
                matches: mediaQuery.match(query, {
                    width: deviceType === 'mobile' ? '0px' : '1024px'
                })
            };
        },
        [userAgent]
    );

你应该通过 userAgent!

然后将 ssrMatchMedia 传递给 MuiUseMediaQuery

<ThemeProvider
                theme={{
                    ...theme,
                    props: {
                        ...theme.props,
                        MuiUseMediaQuery: {
                            ssrMatchMedia
                        }
                    }
                }}>

这应该可行。我没有使用 material-UI v5。使用旧的。 MuiUseMediaQuery 名称可能会更改,但这种方法避免了我的转变。让我知道它是否有效。

【讨论】:

  • 我实际上正在使用 Gatsby。所以从技术上讲,我无法像文档建议的那样访问req.headersnavigator.userAgent 会成功吗?
  • 如果你在服务器端渲染页面,你必须从'request.headers'中获取userAgent。如果您只呈现客户端,而不是我建议的实现,请使用“const matches = useMediaQuery(...some-query, { noSsr: true })”
猜你喜欢
  • 2019-02-27
  • 2021-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-11
相关资源
最近更新 更多