繁体   English   中英

React Functional 组件:作为函数调用与作为组件调用

[英]React Functional component: calling as function vs. as component

假设我有一个功能组件:

const Foo = (props) => ( <div>{props.name}</div> );

直接作为函数调用有什么区别:

const fooParent = () => (
    <div> {Foo({ name: "foo" })} </div>
)

与将其作为组件调用:

const fooParent = () => (
    <div> <Foo name="foo"/> </div>
)

我最感兴趣的是性能影响,React 如何在内部以不同的方式对待它们,也许在 React Fiber 中事情可能会有所不同,我听说功能组件获得了性能提升。

将其作为函数调用要快得多,事实上几个月前就有人讨论过这个问题。 在这一点上,函数式反应组件不能是PureComponents,因此没有真正应用于它们的额外优化。

基本上,如果您可以将功能组件称为消除整个反应生命周期的功能。 如果您考虑一下,您现在可能正在渲染方法中使用此技术。 考虑一下:

... some component ... 

render() {

  const tabHeaders =<TabHeaders>{this.props.tabs.map(this.renderTabHeader)}</TabHeader>;
  const tabContents = <TabContents>{this.props.tabs.map(this.renderTabContent)}</TabContents>;

  return (<div>
    {this.props.tabsBelow?[tabContents, tabHeaders] : [tabHeaders, tabContents]}
  </div>);
} 

renderTabHeader 方法返回一些反应组件,并且可能是功能组件,但在这种情况下只是一些组件类方法。

详细解释见这篇文章: https : //medium.com/missive-app/45-faster-react-functional-components-now-3509a668e69f

另请查看正在执行此操作的 babel 插件:https ://babeljs.io/docs/plugins/transform-react-inline-elements

所以我实际上遇到了一个用例,其中将渲染作为组件而不是函数调用是有益的。 使用 React 16,您可以获得错误边界功能。 这允许您在组件内引发错误时呈现回退错误 UI。 事实证明,如果在函数调用变体中抛出异常,则不会触发componentDidCatch 它需要在子组件中抛出。

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      error: false
    };
  }

  componentDidCatch() {
    this.setState({ error: true});
  }

  render() {
    return this.state.error
      ? "Error :("
      : this.props.children;
  }
}

const renderContent = () => {
  throw new Error();
}

const Content = () => {
  throw new Error();
}

// This will throw exception and not trigger error state
const Foo = () => (
  <ErrorBoundary>
    <div>{renderContent()}</div>
  </ErrorBoundary>
);

// This will trigger the error state
const Bar = () => (
  <ErrorBoundary>
    <div><Content /></div>
  </ErrorBoundary>
);

当然,您可以将错误边界设置得更高,但只需指出一个特定用例,您可以选择其中之一。

此外,出于命名目的,将其渲染为组件也很不错。 它将在 React 开发工具中显示为命名,您也可以在进行酶测试时使用该名称作为选择器。

如果直接调用函数式组件,实际上是在调用自定义钩子。

例子:

function A() {
  const [state] = useState([])
  return (
    <div>{state}</div>
  )
}

A()
<A />

如果你调用A()state挂载在父光纤中,但是如果你使用<A /> ,React 将调用createElement来创建一个新的光纤来挂载state

实际上,当您将其作为组件调用时,会使用React.createElement()创建一个新元素。 另一方面,函数被直接调用。 所以,这就解释了为什么直接调用你的函数会更快。

但请记住,在某些情况下,直接调用函数可能会导致类似@dmwong2268 在这里介绍的问题,或者像这样的问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM