简体   繁体   English

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

[英]How to immediately re-render client-side using React + NextJS after initial server-side render?

I created a website using Next.js with React and really like to declare a js variable to define component styles like this: 我使用带有React的Next.js创建了一个网站,真的很想声明一个js变量来定义组件样式,如下所示:

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

And in the render method I do: 在渲染方法中,我这样做:

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

Using ESLint I can quickly find unused styles/variables (if references are gone) and keep the code clean. 使用ESLint,我可以快速找到未使用的样式/变量(如果引用消失了),并使代码保持干净。 Hence I do not use <style> or styled-jsx like this: 因此,我不会像这样使用<style>styled-jsx

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

The problem 问题

The problem with using only js variables instead of <style> is that I cannot apply media queries to target different screen sizes, so I thought I could fix this using javascript: 仅使用js变量而不是<style>是我无法将媒体查询应用于不同的屏幕尺寸,因此我认为我可以使用javascript来解决此问题:

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

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

I get windowWidth through this workaround: Get viewport/window height in ReactJS . 我通过以下解决方法获取windowWidth在ReactJS中获取视口/窗口高度 This works quite well as long as the rendering happens on the client. 只要在客户端上进行渲染,此效果就很好。 The problem with this approach is that Next.js will render the view first server-side. 这种方法的问题在于,Next.js将首先在服务器端呈现视图。 At this moment in time, the window/screen size is unknown, hence windowWidth = 0 . 此时,窗口/屏幕的大小是未知的,因此windowWidth = 0 Thus, I think that the client has to re-render after receiving the initial rendered page from the server. 因此,我认为客户端必须在从服务器收到初始呈现的页面后重新呈现。

Question(s): 问题:

  1. How can I force the client to immediately re-render after initial render by the server in order to determine the value of windowWidth ? 我如何强制客户端在服务器进行初始渲染后立即重新渲染,以确定windowWidth的值?

  2. Would this be a good practice/solution or would it lead to performance problems or elements flickering? 这是一个好的做法/解决方案,还是会导致性能问题或元素闪烁?

The best way to trigger a render at any time in reactjs is to create the react element with that property. 随时在reactjs中触发渲染的最佳方法是使用该属性创建react元素。 In your case I would calculate which font size to use first, then create the element with that property. 在您的情况下,我将先计算要使用的字体大小,然后使用该属性创建元素。
Font size would not seem to change, but if it did, you'll probably have to put this state in a common parent element of the elements that use it. 字体大小似乎不会改变,但是如果改变了,您可能必须将此状态放在使用它的元素的公共父元素中。 This parent would take this state and give it as props to its children. 该父母将这种状态作为其子女的道具。

As a commenter suggests there are ways of triggering an update, but it's better to reorganize your elements to do this through normal react methods. 正如评论者所建议的那样,有一些触发更新的方法,但是最好通过常规的react方法重新组织元素来做到这一点。 Don't be afraid of making more smaller react elements! 不要害怕制作更小的反应元素!

Found the solution to this. 找到了解决方案。 NextJS will automatically re-render client-side after doing server-side render. 在执行服务器端渲染之后,NextJS将自动重新渲染客户端。 Adding some console output shows this: 添加一些控制台输出将显示以下内容:

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

Render method: 渲染方法:

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

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

Viewing on a small screen, this will print: 在小屏幕上查看,将打印:

12px
24px

However, pressing the browser's reload button, the font size doesn't change although the value of the style variable clearly changed. 但是,按一下浏览器的“重新加载”按钮,尽管样式变量的值明显改变了,但字体大小并没有改变。

The solution was to create a copy of the original object and manipulate that instead: 解决方案是创建原始对象的副本并对其进行操作:

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

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

This will change the font size during runtime. 这将在运行时更改字体大小。 However, when the page loads you will see the old 12px font size for the fraction of a second and when client-side render has finished, it will jump to the new font size of 24px. 但是,在页面加载时,您会在几分之一秒内看到旧的12px字体大小,并且客户端渲染完成后,它将跳到新的24px字体大小。 Not sure if I will go with this from a UX perspective but technically this is a working solution. 不知道我是否会从UX的角度出发,但是从技术上讲这是一个可行的解决方案。 Don't really like it though :-( 虽然不是很喜欢它:-(

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM