Javascript 反应功能组件:作为功能调用与作为组件调用
假设我有一个功能组件:Javascript 反应功能组件:作为功能调用与作为组件调用,javascript,reactjs,Javascript,Reactjs,假设我有一个功能组件: const Foo = (props) => ( <div>{props.name}</div> ); const fooParent = () => ( <div> <Foo name="foo"/> </div> ) constfoo=(props)=>({props.name}); 直接将其作为函数调用有什么区别: const fooParent = () => (
const Foo = (props) => ( <div>{props.name}</div> );
const fooParent = () => (
<div> <Foo name="foo"/> </div>
)
constfoo=(props)=>({props.name});
直接将其作为函数调用有什么区别:
const fooParent = () => (
<div> {Foo({ name: "foo" })} </div>
)
const foopparent=()=>(
{Foo({name:'Foo})}
)
与将其称为组件相比:
const Foo = (props) => ( <div>{props.name}</div> );
const fooParent = () => (
<div> <Foo name="foo"/> </div>
)
const foopparent=()=>(
)
我最感兴趣的是性能影响,React如何在内部对它们进行不同的处理,以及React Fiber中的情况可能会有什么不同,我听说功能组件的性能得到了提升。将其称为函数要快得多,事实上,几个月前就有人谈论过这一点。在这一点上,功能性的react组件不可能实现,因此没有对它们进行额外的优化 基本上,如果您可以将功能组件作为消除整个生命周期的功能调用。如果您仔细想想,您可能正在渲染方法中使用此技术,即使是现在。考虑这一点:
... 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>);
}
。。。某些组件。。。
render(){
const tabHeaders={this.props.tabs.map(this.renderTabHeader)};
const tabContents={this.props.tabs.map(this.renderabcontent)};
返回(
{this.props.tabsBelow?[tabContents,tabHeaders]:[tabHeaders,tabContents]}
);
}
renderTabHeader方法返回一些react组件,可能是功能组件,但在本例中只是一些组件类方法
有关详细说明,请参阅本文:
还可以查看这个babel插件:因此我实际上遇到了一个用例,在这个用例中,作为组件而不是函数调用进行渲染是有益的。使用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>
);
类ErrorBoundary扩展React.Component{
建造师(道具){
超级(道具);
此.state={
错误:false
};
}
componentDidCatch(){
this.setState({error:true});
}
render(){
返回this.state.error
“错误:(”
:这个。道具。儿童;
}
}
常量renderContent=()=>{
抛出新错误();
}
常量内容=()=>{
抛出新错误();
}
//这将引发异常,而不是触发错误状态
常量Foo=()=>(
{renderContent()}
);
//这将触发错误状态
常数条=()=>(
);
当然,您可能会有更高的错误边界,但只是指出一个特定的用例,您可以在其中选择一个
另外,出于命名目的呈现为组件也很好。它将在React-dev工具中显示为named,并且当您进行酶测试时,您也可以使用该名称作为选择器。实际上,当您将其作为组件调用时,将使用
React.createElement()
创建一个新元素。另一方面,直接调用该函数。
这就解释了为什么直接调用函数会更快
但请记住,在某些情况下,直接调用函数可能会导致问题,如@dmwong2268在此处引入的问题,或者类似于如果直接调用函数组件,则实际上是在调用自定义挂钩 例如:
function A() {
const [state] = useState([])
return (
<div>{state}</div>
)
}
A()
<A />
函数A(){
常量[状态]=使用状态([])
返回(
{state}
)
}
()
如果调用
A(),状态
安装在父光纤中,但如果您使用
,React将调用createElement
创建一个新光纤,在其上安装状态您能总结一下为什么将其作为函数调用更快吗?另外,如果没有缺点,那么为什么这样做不是标准?看起来像most文档指出了将功能组件称为组件的方向。啊..这篇文章实际上是我提出这个问题XD的原因。这也是关于React Fiber的部分-这篇文章中有一条评论,暗示已经对功能组件进行了优化,以使其更快。我想知道impac测试结果。正确的方法是测量。但一般来说,你几乎不能比没有代码更快。你能分享一下你在回答中谈论的“谈话”吗?在react的新版本中仍然是这样吗?