如何在使用React + NextJS进行初始服务器端渲染后立即重新渲染客户端?

4
我使用Next.js和React创建了一个网站,并喜欢声明js变量来定义组件样式,例如:
const foo = {
  fontSize: '12px',
};

在render方法中,我执行以下操作:
render() {
  return (
    <div style={foo}>bar</div>
  );
}

使用ESLint可以快速找到未使用的样式或变量(如果引用不存在),保持代码清洁。因此我不使用<style>styled-jsx这样的方式:

render() {
  return (
    <div>
      <style>
        .foo {
          font-size: '12px';
        }
      </style>
      <div className="foo">bar</div>
    </div>
  );
}

问题

只使用JavaScript变量而不使用<style>的问题在于我无法应用媒体查询以针对不同屏幕尺寸进行调整,因此我想使用JavaScript来解决这个问题:

render() {
  // Bigger font size for smaller devices
  if (windowWidth < 768) foo.fontSize = '24px';

  return (
    <div style={foo}>bar</div>
  );
}

我通过这个解决方法获取windowWidth在ReactJS中获取视口/窗口高度。只要渲染发生在客户端,这种方法就很有效。但是这种方法的问题是Next.js会先在服务器端渲染视图。此时,窗口/屏幕大小是未知的,因此windowWidth = 0。因此,我认为客户端必须在接收到来自服务器的初始渲染页面后重新渲染。
问题:
  1. 如何强制客户端在服务器进行初始渲染后立即重新渲染,以确定windowWidth的值?

  2. 这是否是一个好的实践/解决方案,还是会导致性能问题或元素闪烁?


你有考虑在顶层组件中使用forceUpdate吗?但是,我认为你会遇到你在2)中列出的两个问题,这取决于你如何编写样式...如果是移动优先,它们将闪烁,并且可能会触发桌面上的布局重绘,反之亦然。 - Teo Dragovic
您可以尝试在页面上隐藏响应元素,并仅在更新后显示。 - Teo Dragovic
你使用过 componentWillMount 生命周期吗?它应该可以工作。 - simbathesailor
2个回答

2

我找到了解决办法。在进行服务器端渲染后,NextJS会自动重新渲染客户端。添加一些控制台输出可以显示这一点:

const foo = {
  fontSize: '12px',
};

渲染方法:

render() {
  if (windowWidth < 768) {
    foo.fontSize = '24px';
    console.log('24px');
  } else {
    console.log('12px');
  }

  return (
    <div style={foo}>bar</div>
  );
}

在小屏幕上查看,这将打印出:

12px
24px

然而,当点击浏览器的刷新按钮时,字体大小并没有改变,尽管样式变量的值明显已经改变。

解决方法是创建原始对象的副本,并对其进行操作:

render() {
  let foo2;
  if (windowWidth < 768) {
    foo2 = Object.assign({}, foo, { fontSize: '24px' });
  } else {
    foo2 = Object.assign({}, foo);
  }

  return (
    <div style={foo2}>bar</div>
  );
}

这将在运行时更改字体大小。然而,当页面加载时,您会看到旧的12像素字体大小,持续时间很短,当客户端渲染完成后,它将跳转到新的24像素字体大小。从用户体验的角度来看,我不确定是否会选择这种方法,但技术上这是一个可行的解决方案。但我真的不喜欢它 :-(

0

在ReactJS中任何时候触发渲染的最佳方法是使用该属性创建React元素。 在您的情况下,我会先计算要使用的字体大小,然后创建带有该属性的元素。
字体大小似乎不会改变,但如果确实发生了变化,则可能必须将此状态放置在使用它的元素的共同父元素中。 该父元素将获取此状态并将其作为props提供给其子元素。

正如评论者建议的那样,有一些方法可以触发更新,但最好通过常规的React方法重新组织您的元素来进行此操作。 不要害怕制作更多的小型React元素!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接