簡體   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