在React中,如何检测我的组件是从客户端还是服务器呈现?

And*_*ena 31 javascript node.js reactjs

我正在构建一个同构应用程序,但我正在使用仅在客户端上呈现的第三方组件.所以,特别是对于这个组件,我只需要在客户端渲染时才渲染它.

如何检测我是在客户端还是在服务器上?我正在寻找像isClient()或的东西isServer().

Cha*_*tin 37

在内部,React使用ExecutionEnvironment为此调用的实用程序.它实现了一些有用的属性,如canUseDOMcanUseEventListeners.解决方案基本上就是这里的建议.

实施 canUseDOM

var canUseDOM = !!(
  (typeof window !== 'undefined' &&
  window.document && window.document.createElement)
);
Run Code Online (Sandbox Code Playgroud)

我在我的应用程序中使用这个

var ExecutionEnvironment = require('react/node_modules/fbjs/lib/ExecutionEnvironment');
...
render() {
  <div>{ ExecutionEnvironment.canUseDOM ? this.renderMyComponent() : null }</div>
}
Run Code Online (Sandbox Code Playgroud)

编辑这是一个未记录的功能,不应直接使用.它的位置可能会因版本而异.我通过展示Facebook团队内部使用的内容,将此作为一种说法"这是你能做的最好"的方式.您可能希望将此代码(它很小)复制到您自己的项目中,因此您不必担心跟踪其版本之间的位置或潜在的重大更改.

另一个编辑有人为此代码创建了一个npm包.我建议使用它.

npm install exenv --save
Run Code Online (Sandbox Code Playgroud)

  • `!!` 将值转换为布尔值,以确保返回 `true` 或 `false`,而不是潜在的 `undefined`。你可以用“Boolean”替换上面的“!!”并得到相同的结果 (2认同)

HaN*_*riX 12

您可以使用 reacts lifecyle事件(例如:)componentDidMount来检测服务器/客户端渲染。

例子

作为钩

import { useState, useEffect } from 'react'

function useIsServer () {
  const [isServer, setIsServer] = useState(true)
  useEffect(() => {
    setIsServer(false)
  }, [])
  return isServer
}
Run Code Online (Sandbox Code Playgroud)

用法

见下文(功能组件)

作为功​​能组件

import useIsServer from './above'

function ServerOnly ({ children = null, onClient = null }) {
  const isServer = useIsServer()
  return isServer
    ? children
    : onClient
}
Run Code Online (Sandbox Code Playgroud)

用法

<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>
Run Code Online (Sandbox Code Playgroud)

作为类组件

<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>
Run Code Online (Sandbox Code Playgroud)

用法

<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>
Run Code Online (Sandbox Code Playgroud)


And*_*Ray 9

两件可能相关的事情:

许多项目使用一些约定来设置全局SERVER或CLIENT布尔值,因此所有代码都可以根据它进行切换.在您的服务器包中,设置一些全局,就像在此项目中一样

global.__SERVER__ = true;
Run Code Online (Sandbox Code Playgroud)

在您的客户端包中,将一些全局客户端设置为true,您可以使用Webpack的DefinePlugin实现一种方式

new webpack.DefinePlugin({
  __CLIENT__: true
})
Run Code Online (Sandbox Code Playgroud)

使用上述方法,您可以在willMount或render中基于该变量进行切换,以在服务器上执行一项操作,在客户端上执行另一项操作.

这里可能有用的第二件事是componentDidMount只在客户端上运行,但不在服务器上运行.


Joe*_*dee 5

您也可以使用componentDidMount(),因为在服务器端呈现页面时不会运行此生命周期方法。