繁体   English   中英

React hooks:将组件作为函数调用与作为元素渲染

[英]React hooks: call component as function vs render as element

假设我们有组件:

let Component = (props)=><div>Hi</div>;

我经常遇到这样的代码,其中有人在渲染中将 react 组件称为函数

 const App = () => (
     <div> {Component()} </div>
 )

vs将其渲染为元素

 const App = () => (
     <div> <Component/> </div>
 )

在反应钩子中,推荐的做法是什么?


类似的问题,但它不是专门针对钩子的(它更多的是关于性能)。 使用钩子的情况似乎有些不同,将其称为函数更像是反模式。

TL DR ; 在大多数情况下你想要<Component/>


以下是一些原因:

  1. 可能违反钩子规则

当你调用一个组件作为一个功能(参见TestB()下图),它包含在它里面的钩子的使用,在这种情况下,反应认为钩的功能属于组件。 现在,如果您有条件地渲染该组件(例如TestB() ),您将违反钩子规则之一。 检查下面的示例,单击重新渲染按钮以查看错误:

错误:呈现的钩子比预期的少。 这可能是由意外的提前退货声明引起的。

 function TestB() { let [B, setB] = React.useState(0); return ( <div onClick={() => { setB(B + 1); }} > counter B {B} </div> ); } function App() { let [A, setA] = React.useState(0); return ( <div> <button onClick={() => { setA(A + 1); }} > re-render </button> {/* Conditionally render TestB() */} {A % 2 == 0 ? TestB() : null} </div> ); } ReactDOM.render( <App />, document.getElementById("react") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="react"></div>

现在您可以改用<TestB/>并查看不同之处。

  1. 对帐可能无法按预期进行

当您将反应组件渲染为反应元素时说<TestB/>然后在下一次渲染时渲染一些不同的组件<TestC/>而不是它(在组件层次结构中的同一位置),由于协调算法(并且由于组件类型has changed ),react 将卸载<TestB/>组件(它的所有状态都将消失)并安装一个新组件<TestC/>代替。

但是,如果您将其称为函数(例如TestB() ),则组件类型将不再参与协调,您可能无法获得预期结果:

 function TestB() { return ( <div > <input/> </div> ); } function TestC() { console.log("TestC") return ( <div > <input/> </div> ); } function App() { let [A, setA] = React.useState(0); return ( <div> <button onClick={() => { setA(A + 1); }} > re-render </button> {/* Here we are alternating rendering of components */} {A % 2 == 0 ? TestB() : TestC()} </div> ); } ReactDOM.render( <App />, document.getElementById("react") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="react"></div>

  • 在输入中输入一些东西
  • 现在单击重新渲染按钮
  • 您现在可以从日志中看到组件TestC已呈现,但输入显示的值与您之前键入的值相同(当您呈现不同的组件时,这可能不是您想要的)。 发生这种情况是因为反应协调算法无法检测到我们移动到不同的组件(从TestBTestC )并且没有从 DOM 中删除以前的输入实例。

现在将这些组件渲染为元素( <TestB/><TestC/> )以查看差异。

暂无
暂无

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

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