【问题标题】:How to detect a React component vs. a React element?如何检测 React 组件与 React 元素?
【发布时间】:2016-01-16 22:43:19
【问题描述】:

React.isValidElement 为 React 组件和 React 元素测试 true。具体来说,我将如何测试一个对象是一个 React 组件?目前,我正在通过测试typeof obj.type === 'function' 来做到这一点,但我希望有更好的方法。

【问题讨论】:

  • obj.type 也可以是符号或字符串。

标签: javascript reactjs


【解决方案1】:
ReactComponent.prototype.isReactComponent = {};

/node_modules/react/lib/ReactComponent.js 的 33 个

使用 npm 安装。在这一点上,没有直接的方法可以检查其有效性。你的做法是正确的。

【讨论】:

  • 以上方案不坚持安装node模块。它指的是代码中的一行以供更多参考。
  • Dan Abramov:“.isReactComponent 是一个 impl 细节,我们保留将来更改它的权利”(twitter.com/dan_abramov/status/787739945301635073)
  • 我使用了instanceof(),它运行良好,只有 10 个字符,而 ReactComponent.js 是一个完整的包。为什么不直接使用更短的内置功能?
【解决方案2】:

如果你真的想输入检查

  • 组件与元素

  • 类与功能组件

  • DOM 与复合元素

你可以试试这样的。

function isClassComponent(component) {
    return (
        typeof component === 'function' && 
        !!component.prototype.isReactComponent
    )
}

function isFunctionComponent(component) {
    return (
        typeof component === 'function' && 
        String(component).includes('return React.createElement')
    )
}

function isReactComponent(component) {
    return (
        isClassComponent(component) || 
        isFunctionComponent(component)
    )
}

function isElement(element) {
    return React.isValidElement(element);
}

function isDOMTypeElement(element) {
    return isElement(element) && typeof element.type === 'string';
}

function isCompositeTypeElement(element) {
    return isElement(element) && typeof element.type === 'function';
}

使用

// CLASS BASED COMPONENT
class Foo extends React.Component {
  render(){
      return <h1>Hello</h1>;
  }
}

const foo = <Foo />;

//FUNCTIONAL COMPONENT
function Bar (props) { return <h1>World</h1> }
const bar = <Bar />;

// REACT ELEMENT
const header = <h1>Title</h1>;

// CHECK
isReactComponent(Foo); // true
isClassComponent(Foo); // true
isFunctionComponent(Foo); // false
isElement(Foo); // false

isReactComponent(<Foo />) // false
isElement(<Foo />) // true
isDOMTypeElement(<Foo />) // false
isCompositeTypeElement(<Foo />) // true

isReactComponent(Bar); // true
isClassComponent(Bar); // false
isFunctionComponent(Bar); // true
isElement(Bar); // false

isReactComponent(<Bar />) // false
isElement(<Bar />) // true
isDOMTypeElement(<Bar />) // false
isCompositeTypeElement(<Bar />) // true

isReactComponent(header); // false
isElement(header); // true
isDOMTypeElement(header) // true
isCompositeTypeElement(header) // false

Example Codepen

【讨论】:

  • 该帖子似乎缺少任何解释您发布代码的原因以及代码的预期使用方式。这使得它从 SO 标准中得到低质量的答案。
  • 我猜 isFunctionComponent 的情况不再有效。通过检查我发现了类似function FnChild(props) { return _react2.default.createElement('div', { id: 'child-fn' }); }
  • 投反对票,因为您没有提到String(component).includes('return React.createElement') 在很多情况下都不起作用。
  • 不错的解决方案。这真有趣。谢谢
  • isFunctionComponent 对于一般用例和编写单元测试时不可靠。另外,如果我模仿 React 函数组件结构及其实例,这将无法检测到真正的组件。
【解决方案3】:

除了@EmanualJade 答案,您还可以使用它来检查变量是否为function component

React.isValidElement(Component())

正如@Leonardo 所指出的,某些编译器可能会导致此操作失败:

String(component).includes('return React.createElement')

【讨论】:

  • 这感觉更适合作为评论而不是答案。
  • 这是一个很好的解决方案。检查是否是typeof component === 'function' &amp;&amp; !!React.isValidElement(component())之前的函数
【解决方案4】:

如果您想知道对于对象变量的特定实例有什么,那么你想要的是instanceof 运算符...

function isHTMLElement(obj) {
    return (obj instanceof HTMLElement);
}

我测试了document.createElement('div')(返回真)和&lt;someReactJSComponent /&gt;(返回假)。

instanceof 是 JavaScript 中一个强大而有用的工具。查看官方 MDN 文档:Mozilla Documentation Network: instanceof

“instanceof 操作符测试对象的原型链中是否存在constructor.prototype。”

另外,我在网上上传了一个带有code-sandbox的代码示例来演示以上原理...

在线代码沙箱:

https://codesandbox.io/s/kmxjq27ol5

代码:

function App() { return (//insert JSX here//);};
const app = App();
const ele = document.createElement("div");
const rootElement = document.getElementById("root");
ReactDOM.render(app, rootElement);
console.log(
  "Hello!  Is a React Component HTML???" +
    (app instanceof HTMLElement) +
    "|  Is an HTML element HTML???" +
    (ele instanceof HTMLElement) +
    "|"
);

代码结果:

Hello!  Is a React Element HTML???false|  Is an HTML element HTML???true|

没问题(测试过 Chrome 和 FF)。只需使用instanceof

【讨论】:

  • A React 组件不是 html,这就是你所证明的,这如何回答这个问题。
  • 嗨,为了好玩而学习!感谢您的评论! instanceOf 在 MDN 开发人员文档中有详细记录。如果这个答案有任何用处,那就是在我发布的简单的 2 行沙盒演示中使用时,此页面上的所有其他答案都将失败。干杯!
  • 所以你的意思是,当涉及到 HTMLElements 时,没有一个答案会起作用?
  • 嗨,为了好玩而学习!我不确定你在问什么?你不能只是想让我确认我刚才所说的话。所以,这是一个得分最高的演示:codesandbox.io/s/stupefied-shockley-k7krn?file=/src/index.js 代码:var testcomp = &lt;TestComponent /&gt;; console.log("TEST " + isClassComponent(testcomp) + "|"); // Results: "TEST false"。请注意其他函数,以确定是否为 react-element,使用 isClassComponent(),但对于合法的 React 类组件,它返回 false。希望这会有所帮助!
【解决方案5】:

class Test extends React.Component {}

console.log(!!Test.prototype.isReactComponent);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

【讨论】:

    【解决方案6】:

    最简单的解决方案是:

    React.isValidElement(element)
    

    【讨论】:

    • 可能还需要先做一个typeof element === 'function'。我试图渲染一个字符串或一个 React 组件
    • 我得到了false 一个工作的、功能性的 React 组件,使用这个方法:/
    • 这篇文章发布后已经过了很长时间。我想这种方法现在不是最终的解决方案。如果现在不起作用,请尝试使用其他建议。
    【解决方案7】:

    这是一个老问题,有一个老答案。

    如果您遇到此问题,您可能需要查看react-is NPM 包页面:https://www.npmjs.com/package/react-is

    这是一个官方的 React 模块,它考虑了诸如 ref 转发和检查元素类型的备忘录等细节。

    要检查值是否为元素类型,请执行以下操作:ReactIs.isValidElementType(obj)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-18
      • 2018-03-07
      • 1970-01-01
      • 2014-08-19
      • 1970-01-01
      • 2017-10-08
      • 2015-09-07
      • 1970-01-01
      相关资源
      最近更新 更多