当代码需要设备宽度时,ReactDOMServer 如何表现?

How does ReactDOMServer behave when code needs the device width?

我使用以下挂钩在整个应用程序中构建响应式组件。

我正在考虑实施服务器端渲染。

useWindowWidth.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;

App.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 遇到这种情况是什么行为?这种情况的解决方法是什么?

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

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

或如 docs 所述:

If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like this.state.isClient, which you can set to true in componentDidMount(). This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. Note that this approach will make your components slower because they have to render twice, so use it with caution.