首页 > 解决方案 > 当代码需要设备宽度时,ReactDOMServer 的行为如何?

问题描述

我有以下钩子,用于在整个应用程序中构建响应式组件。

我正在研究实现服务器端渲染。

使用WindowWidth.js

import {useEffect, useRef, useState} from 'react';

function useWindowWidth() {
  const hasResized = useRef(false);
  const [windowSize,setWindowSize] = useState(window.innerWidth);

  useEffect(() => {

    function handleResize() {
      if (hasResized.current === true) {
        return;
      }
      hasResized.current = true;
      throtled_forceUpdate();
    }

    function throtled_forceUpdate() {
      setTimeout(()=>{
        // console.log('I will be updated!');
        // console.log(window.innerWidth);
        setWindowSize(window.innerWidth);
        hasResized.current = false;
      },250);
    }

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return windowSize;

}

export default useWindowWidth;

应用程序.js

import React from 'react';
import useWindowWidth from './hooks/useWindowWidth';

function App(props) {

  const windowWidth = useWindowWidth();

  return(
    windowWidth > 1200 ?
      <DesktopLayout/>
    : <MobileLayout/>
  );
}

ReactDOMServer

ReactDOMServer.renderToString(App);

当 ReactDOMServer 遇到这样的事情时,它的行为是什么?这种情况的解决方法是什么?

标签: javascriptreactjsserver-side-renderingreact-domreact-dom-server

解决方案


无法在服务器端获取窗口宽度。一种解决方法是使用传入请求中的用户代理来确定应该在服务器上呈现哪个组件。

const deviceType = useDeviceType();
return deviceType === 'mobile' ? <MobileLayout /> : <DesktopLayout />;

或者正如文档提到的:

如果您有意在服务器和客户端上渲染不同的东西,您可以进行两次渲染。在客户端呈现不同内容的组件可以读取像 this.state.isClient 这样的状态变量,您可以在 componentDidMount() 中将其设置为 true。这样,初始渲染通道将渲染与服务器相同的内容,避免不匹配,但额外的通道将在水化后立即同步发生。请注意,这种方法会使您的组件变慢,因为它们必须渲染两次,因此请谨慎使用。


推荐阅读