简体   繁体   English

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

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

Say I have a functional component:假设我有一个功能组件:

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

What is the difference between calling it directly as a function:直接作为函数调用有什么区别:

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

versus calling it as a component:与将其作为组件调用:

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

I'm mostly interested in performance implications, how React treats them differently internally, and perhaps how things might be different in React Fiber, where I hear functional components got a performance boost.我最感兴趣的是性能影响,React 如何在内部以不同的方式对待它们,也许在 React Fiber 中事情可能会有所不同,我听说功能组件获得了性能提升。

Calling it as a function is much faster, in fact there was a talk exactly about this few months ago.将其作为函数调用要快得多,事实上几个月前就有人讨论过这个问题。 At this point functional react components can't be PureComponents so no extra optimizations really applied to them.在这一点上,函数式反应组件不能是PureComponents,因此没有真正应用于它们的额外优化。

Basically if you can call functional component as a function that eliminates whole react lifecycle.基本上,如果您可以将功能组件称为消除整个反应生命周期的功能。 If you think about it you are probably using this technique inside your render method even right now.如果您考虑一下,您现在可能正在渲染方法中使用此技术。 Consider this:考虑一下:

... 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 method returns some react components, and could've been functional components but in this case is just some component class method. renderTabHeader 方法返回一些反应组件,并且可能是功能组件,但在这种情况下只是一些组件类方法。

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

Also check out this babel plugin that is doing that:https://babeljs.io/docs/plugins/transform-react-inline-elements另请查看正在执行此操作的 babel 插件:https ://babeljs.io/docs/plugins/transform-react-inline-elements

So I actually ran into a use case where it is beneficial to render as a component rather than a function call.所以我实际上遇到了一个用例,其中将渲染作为组件而不是函数调用是有益的。 With React 16, you get the error boundaries feature.使用 React 16,您可以获得错误边界功能。 This allows you to render fallback error UIs when an error is thrown within the component.这允许您在组件内引发错误时呈现回退错误 UI。 Turns out, if an exception is thrown in the function call variation, it won't trigger componentDidCatch .事实证明,如果在函数调用变体中抛出异常,则不会触发componentDidCatch It needs to be thrown within a child component.它需要在子组件中抛出。

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>
);

Of course, you could have an error boundary higher up, but just pointing out one specific use case where you may choose one of the other.当然,您可以将错误边界设置得更高,但只需指出一个特定用例,您可以选择其中之一。

Also, it's nice to render as component for naming purposes.此外,出于命名目的,将其渲染为组件也很不错。 It will show up named in React dev tools, and also you can use the name as selectors when you do Enzyme testing.它将在 React 开发工具中显示为命名,您也可以在进行酶测试时使用该名称作为选择器。

If you call functional component directly, you are calling a custom hook actually.如果直接调用函数式组件,实际上是在调用自定义钩子。

example:例子:

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

A()
<A />

If you call A() , the state mounts in parent fiber, but if you use <A /> , React will call createElement to create a new fiber on which to mount state .如果你调用A()state挂载在父光纤中,但是如果你使用<A /> ,React 将调用createElement来创建一个新的光纤来挂载state

Actually, when you call it as a component a new element is created with React.createElement() .实际上,当您将其作为组件调用时,会使用React.createElement()创建一个新元素。 On the other hand, the function is called directly.另一方面,函数被直接调用。 So, that explains a little bit why calling your function directly is faster.所以,这就解释了为什么直接调用你的函数会更快。

But keep in mind, that in some cases calling a function directly may cause problems like the one introduced by @dmwong2268 here, or like this one但请记住,在某些情况下,直接调用函数可能会导致类似@dmwong2268 在这里介绍的问题,或者像这样的问题

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

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