[英]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/>
以下是一些原因:
當你調用一個組件作為一個功能(參見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/>
並查看不同之處。
當您將反應組件渲染為反應元素時說<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
已呈現,但輸入顯示的值與您之前鍵入的值相同(當您呈現不同的組件時,這可能不是您想要的)。 發生這種情況是因為反應協調算法無法檢測到我們移動到不同的組件(從TestB
到TestC
)並且沒有從 DOM 中刪除以前的輸入實例。 現在將這些組件渲染為元素( <TestB/>
和<TestC/>
)以查看差異。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.