0

我正在使用一个React 组件,该组件根据是否支持 CSSbackdrop-filter指令使用不同的不透明度值:

background={(() => {
  const opacity = isBackdropFilterSupported() ? 0.75 : 0.98
  return (
    `linear-gradient(
      180deg, rgba(76, 63, 143, ${opacity}) 62.76%,
      rgba(184, 169, 255, ${opacity}) 100%
    )`
  )
})()}

问题是该站点是使用 Next.js 在服务器端生成的。CSS.supports('backdrop-filter', 'blur(1px)')在服务器上返回false,因此该值始终false与客户端属性无关。

一种解决方案是使用 CSS,例如:

.drawer {
  --opacity: 0.75;
  background: linear-gradient(
    180deg, rgba(76, 63, 143, var(--opacity)) 62.76%,
    rgba(184, 169, 255, var(--opacity)) 100%
  );
}
@supports not (backdrop-filter: blur(1px)) {
  .drawer { --opacity: 0.98; }
}

这应该由客户端解释并避免服务器端呈现问题,但我没有发现有关如何将这种样式集成到它所构建的 Chakra-UI 中的迹象。

4

1 回答 1

0

我没有在我的原始帖子中提到它,但我收到了一个错误,例如:Prop id did not match. Server: "toggle--gxfg3t7xwo" Client: "toggle--ki0j10p2l".

事实证明,这意味着浏览器生成的 DOM 与 Next.js 生成的 DOM 不匹配。当发生这种情况时,Next.js 放弃尝试重新水化文档,这就是我获取服务器渲染值的原因。

解决方案是使用挂钩来确定组件的安装时间(这只发生在客户端上)。那个钩子看起来像:

export const useMounted = () => {
  // https://www.joshwcomeau.com/react/the-perils-of-rehydration/
  const [hasMounted, setHasMounted] = React.useState(false);
  React.useEffect(() => {
    setHasMounted(true);
  }, []);
  return hasMounted;
};

然后不透明度确定变为:

const hasMounted = useMounted()
⋮
const opacity = hasMounted && isBackdropFilterSupported() ? 0.75 : 0.98
于 2021-02-04T23:52:39.187 回答