探討React自訂元件中的條件渲染挑戰
P粉301523298
P粉301523298 2023-08-18 15:58:43
0
2
592
<p>我在我的React應用程式中的自訂元件中遇到了條件渲染的問題。我一直在努力創建一個用於條件渲染的自訂元件,只有在滿足特定條件時才渲染內容。以下是我目前的程式碼:</p> <pre class="brush:js;toolbar:false;">import React from 'react'; function ConditionalRenderComponent({ condition, children }) { return ( <div> {condition && children} </div> ); } export default ConditionalRenderComponent; </pre> <p>在使用這個自訂元件時,我注意到透過<code>children</code>屬性傳遞的內容即使<code>condition</code>為<code>false</code>時也被訪問和執行。這與直接使用<code>condition && <div></div></code>而沒有自訂元件的行為不同,後者在條件為<code>false</code>時正確地阻止了內容的存取。 </p> <p><strong>以下是我使用自訂元件的方式:</strong></p> <pre class="brush:js;toolbar:false;">import React, { useState, useEffect } from 'react'; import ConditionalRenderComponent from './ConditionalRenderComponent'; function App() { const [userData, setUserData] = useState(null); const isLoggedIn = userData !== null; useEffect(() => { setTimeout(() => { setUserData({ username: 'john_doe', email: 'john@example.com' }); }, 1000); }, []); return ( <div> <h1>歡迎來到我的應用程式</h1> <ConditionalRenderComponent condition={isLoggedIn}> <div> <p>你好,{userData.username}! </p> <p>你的信箱:{userData.email}</p> </div> </ConditionalRenderComponent> {!isLoggedIn && <p>請登入以存取使用者資料。 </p>} </div> ); } export default App; </pre> <p>在上面的範例中,<code>userData</code>最初為<code>null</code>,稍後透過從伺服器擷取的資料進行填入。 <code>isLoggedIn</code>條件取決於<code>userData</code>是否填入。 </p> <p>然而,即使<code>isLoggedIn</code>條件為<code>false</code>(在獲取資料之前),<code>ConditionalRenderComponent</code>內部的內容<code>ConditionalRenderComponent</code>內部的內容」仍然嘗試存取和顯示<code>userData</code>。這導致錯誤訊息:「TypeError: Cannot read properties of null (reading 'username')」。 </p> <p><strong>與標準條件渲染的比較:</strong></p> <p>以下是使用標準的<code>condition && <div></div></code>方法的行為比較:</p> <pre class="brush:js;toolbar:false;">// 標準條件渲染 {isLoggedIn && ( <div> <p>你好,{userData.username}! </p> <p>你的信箱:{userData.email}</p> </div> )} </pre> <p>如上面的程式碼所示,使用標準方法可以在條件為<code>false</code>時正確地阻止存取<code>userData</code>的值。 </p> <p>我不確定為什麼在使用帶有<code>children</code>屬性的自訂元件時會出現這種行為差異。我已經嘗試過調試和尋找解決方案,但我還沒有找到明確的答案。 </p> <p>非常感謝您提供的任何見解或建議,以解釋可能發生的原因以及如何修改自訂元件以實現對<code>children</code>屬性的預期條件渲染行為。 </p> <p>提前感謝您的幫忙! </p>
P粉301523298
P粉301523298

全部回覆(2)
P粉533898694

為什麼會發生這種情況?

所以我認為發生這種情況的原因是,在ConditionalRenderComponent元件中,子元素被當作屬性傳遞給它(就像函數的參數一樣)。 JSX表達式被當作函數的參數來評估。

這意味著即使condition為false,children在傳遞給ConditionalRenderComponent函數之前仍然會被評估。

易於理解的範例

你把一個PlayStation(在你的左手)和數學試捲成績(在你的右手)給了一個孩子,並說如果他/她的分數超過90 /100,他/她就會得到PlayStation。

由於孩子已經可以看到你左手中的PlayStation(將children作為JSX表達式傳遞),他/她在檢查條件之前就已經開始使用了。

現在,如果你握緊你的拳頭,相當於將children作為函數傳遞,他/她在檢查你右手中的條件是否為真之前無法評估左手中的內容。

解決方案

我們透過使用函數作為子元素來修改我們的自訂元件,而不是直接在元件中渲染children。這樣,您可以確保只有在condition為真時才會評估children

對ConditionalRenderComponent的更改

function ConditionalRenderComponent({ condition, children }) {
  return (
    <div>
      {condition && children()}
    </div>
  );
}

渲染ConditionalRenderComponent的改變

<ConditionalRenderComponent condition={isLoggedIn}>
        {() => (
          <div>
            <p>你好,{userData.username}!</p>
            <p>你的电子邮件:{userData.email}</p>
          </div>
        )}
</ConditionalRenderComponent>
P粉543344381

我不建議為條件渲染建立一個元件,但如果你想這樣做,你可以使用渲染屬性模式,這樣只有在條件為真時才呼叫函數。這樣可以防止表達式立即被評估。

function If({ condition, render }) {
  if (!condition) return null;

  return render();
}

export default function App() {
  const [state, setState] = useState(null);

  useEffect(() => {
    wait(1000).then(() => {
      setState({ hello: "world" });
    });
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>

      <If condition={Boolean(state)} render={() => <p>{state.hello}</p>} />
    </div>
  );
}

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板