什么是React组件-无效的挂钩调用

时间:2020-11-06 21:42:04

标签: reactjs

请考虑以下内容:

function Welcome(props) {
  return <h1>Hello World</h1>;
}

ReactDOM.render(<Welcome />, document.getElementById('root'));
// React.createElement(Welcome, null)

通过直接调用该功能而不是使用JSX可以实现相同的目的

ReactDOM.render(Welcome(), document.getElementById('root'));

现在我不建议您应该执行此操作,但是我已经看到组件多次以这种方式调用,即

<div>
  {SomeComponentOrJSX()}
</div>

它有效。

但是,当您尝试使用钩子时,它会崩溃:

function Counter() {
  const [count, setCount] = React.useState(0);
  return (
    <>
      <h1>{count}</h1>
      <button onClick={() => setCount(x => x + 1)}>Increment</button>
    </>
  )
}

这仅在使用React.createElement(Counter, null)<Counter />渲染时才有效

// Works
ReactDOM.render(<Counter />, document.getElementById('root'));

如果您直接调用该函数,将无法正常工作

// Does not work
ReactDOM.render(Counter(), document.getElementById('root'));

它提供的错误是臭名昭著的

  Invalid hook call. Hooks can only be called inside of the body of a function component.

这是为什么?

这里的简单答案是不这样做。同意但是,我想更深入地探讨为什么在这种情况下失败了。

我曾经认为React组件只是函数定义,但现在我不确定。因此,对我来说,React组件不仅是定义,而且是使用React.createElement()

来创建元素

1 个答案:

答案 0 :(得分:0)

您可能知道,例如<Hello />转换为React.createElement(Hello, null);,然后React.createElement返回一个React知道如何管理的魔术对象(因此,任何React.createElement调用我们都可以称其为“组件边界” “)。

React会严格跟踪组件边界(请注意,挂钩规则仅在组件边界内起作用)。钩子(就像类组件的生命周期方法一样!)是在React的渲染阶段发生的魔术。如果直接调用Hello(),则意味着您正在颠覆组件的生命周期,因此,钩子失去了魔力,一切都破了。 (对于类组件,您可以执行(new ClassComponent(someProps)).render()来执行相同的操作。)