首頁  >  問答  >  主體

探討React自訂元件中的條件渲染挑戰

<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粉301523298P粉301523298400 天前503

全部回覆(2)我來回復

  • P粉533898694

    P粉5338986942023-08-19 15:04:37

    為什麼會發生這種情況?

    所以我認為發生這種情況的原因是,在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>

    回覆
    0
  • P粉543344381

    P粉5433443812023-08-19 13:02:01

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

    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>
      );
    }

    回覆
    0
  • 取消回覆