Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在React中,如何检测组件是从客户端还是从服务器渲染?_Javascript_Node.js_Reactjs - Fatal编程技术网

Javascript 在React中,如何检测组件是从客户端还是从服务器渲染?

Javascript 在React中,如何检测组件是从客户端还是从服务器渲染?,javascript,node.js,reactjs,Javascript,Node.js,Reactjs,我正在构建一个同构的应用程序,但我使用的是只在客户端呈现的第三方组件。因此,特别是对于这个组件,我只需要在客户端渲染时渲染它 如何检测我是在客户端还是在服务器上?我正在寻找类似于isClient()或isServer()的东西。在内部,React使用一个名为ExecutionEnvironment的实用程序来实现这一点。它实现了一些有用的属性,如canUseDOM和canuseventlisteners。不过,解决方案基本上就是我们所建议的 canUseDOM的实现 var canUseDOM

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


如何检测我是在客户端还是在服务器上?我正在寻找类似于
isClient()
isServer()
的东西。在内部,React使用一个名为
ExecutionEnvironment
的实用程序来实现这一点。它实现了一些有用的属性,如
canUseDOM
canuseventlisteners
。不过,解决方案基本上就是我们所建议的

canUseDOM的实现

var canUseDOM = !!(
  (typeof window !== 'undefined' &&
  window.document && window.document.createElement)
);
我在我的应用程序中这样使用它

var ExecutionEnvironment = require('react/node_modules/fbjs/lib/ExecutionEnvironment');
...
render() {
  <div>{ ExecutionEnvironment.canUseDOM ? this.renderMyComponent() : null }</div>
}
function my_function_for_browser_only(arg1: number, arg2: string) {}

onClient(my_function_for_browser_only)(123, "Hi !");

有两件事可能是相关的:

许多项目使用某种约定,在这种约定中,它们设置了一个全局服务器或客户端布尔值,以便您的所有代码都可以基于它进行切换。在服务器包中,设置一些全局

在您的客户机包中,将某个全局客户机设置为true,这可以通过一种方式实现

使用上述方法,您可以在willMount或render中关闭该变量,在服务器上执行一项操作,在客户端执行另一项操作


第二件可能有用的事情是
componentDidMount
仅在客户端上运行,而不在服务器上运行

在服务器元素层次结构的最顶层,可以添加一个
ServerContext
,如下所示:

class ServerContext extends React.Component {
  getChildContext() { return { isServer: true }; }
  render() { return React.Children.only(this.props.children); }
}

ServerContext.propTypes = {
  children: React.PropTypes.node.isRequired,
};

ServerContext.childContextTypes = {
  isServer: React.PropTypes.bool.isRequired,
};

// Create our React application element.
const reactAppElement = (
  <ServerContext>
    <CodeSplitProvider context={codeSplitContext}>
      <ServerRouter location={request.url} context={reactRouterContext}>
        <DemoApp />
      </ServerRouter>
    </CodeSplitProvider>
  </ServerContext>
);

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

您可以在
exenv
包的帮助下创建一个有用的实用程序

import { canUseDOM } from 'exenv';

export function onClient(fn: (..._args: any[]) => any): (..._args: any[]) => any {
    if (canUseDOM) {
        return fn;
    }

    if (process.env.NODE_ENV === 'development') {
        console.log(`Called ${fn.name} on client side only`);
    }

    return (): void => {};
}
像这样使用它

var ExecutionEnvironment = require('react/node_modules/fbjs/lib/ExecutionEnvironment');
...
render() {
  <div>{ ExecutionEnvironment.canUseDOM ? this.renderMyComponent() : null }</div>
}
function my_function_for_browser_only(arg1: number, arg2: string) {}

onClient(my_function_for_browser_only)(123, "Hi !");
如果您设置
NODE\u ENV=development

(这是typescript,删除JS的类型:)

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

例子 作为钩子
从'react'导入{useState,useffect}
函数useIsServer(){
常量[isServer,setIsServer]=useState(真)
useffect(()=>{
setIsServer(错误)
}, [])
返回isServer
}
用法

<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>
<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>
见下文(功能组件)

作为功能部件
从“/以上”导入UseiServer
函数ServerOnly({children=null,onClient=null}){
const isServer=useIsServer()
返回isServer
儿童
:onClient
}
用法

<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>
<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>
用法

<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>
<ServerOnly
  children='This String was rendered on the server'
  onClient='This String was rendered on the client'
/>

您也可以使用React钩子

import useSSR from 'use-ssr'

const App = () => {
  var { isBrowser, isServer } = useSSR()

  // Want array destructuring? You can do that too!
  var [isBrowser, isServer] = useSSR()

  /*
   * In your browser's chrome devtools console you should see
   * > IS BROWSER: You can check if global 
window
variable is defined or not. as in browser it should always be defined.

var isBrowser = window!==undefined
从“使用ssr”导入使用ssr
常量应用=()=>{
var{isBrowser,isServer}=useSSR()
//想要阵列分解?你也可以!
var[isBrowser,isServer]=useSSR()
/*
*在浏览器的ChromeDevTools控制台中,您应该可以看到

*>IS BROWSER:您可以检查是否定义了全局
窗口
变量。 和在浏览器中一样,应该始终定义它

if (typeof window === "undefined") { //client side code }

如果没有
typeof
,你会出现一个错误。

你不能检查一些全局的,比如
window
,或者
process
?类似的:谢谢@elclars和@zerkms。这是我想到的第一件事,但是我尝试了
if(windows){/code>,而实际上我应该做
typeof window
ReactDOM.render(,document.getElementById('root'),()=>console.log('render!))
你能回顾一下我的答案吗?如果有什么问题,请更正。数组解构对我不起作用。我使用了对象解构。只是好奇,为什么开始时!!将值转换为布尔值,以确保返回
true
false
,而不是potentially
undefined
。您可以将上面的
!!
替换为
Boolean
,并获得相同的结果。在这里,我们使用
&
运算符,我看不到最终返回未定义的路径,或者返回true或false以外的其他值。我错了吗?如果
window.document
存在,但没有
createElement
方法,这将返回
未定义的
。如果它确实有
createElement
方法,它将返回该方法,也称为函数。要测试这一点,您可以复制并粘贴到javascript控制台中(不带
!!
),并查看它是否返回函数