探讨React自定义组件中的条件渲染挑战
P粉301523298
P粉301523298 2023-08-18 15:58:43
[React讨论组]

我在我的React应用程序中的自定义组件中遇到了条件渲染的问题。我一直在努力创建一个用于条件渲染的自定义组件,只有在满足特定条件时才渲染内容。以下是我目前的代码:

import React from 'react';

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

export default ConditionalRenderComponent;

在使用这个自定义组件时,我注意到通过children属性传递的内容即使conditionfalse时也被访问和执行。这与直接使用condition && <div></div>而没有自定义组件的行为不同,后者在条件为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;

在上面的示例中,userData最初为null,稍后通过从服务器检索到的数据进行填充。isLoggedIn条件取决于userData是否填充。

然而,即使isLoggedIn条件为false(在获取数据之前),ConditionalRenderComponent内部的内容仍然尝试访问和显示userData。这导致错误消息:“TypeError: Cannot read properties of null (reading 'username')”。

与标准条件渲染的比较:

以下是使用标准的condition && <div></div>方法的行为比较:

// 标准条件渲染
{isLoggedIn && (
  <div>
    <p>你好,{userData.username}!</p>
    <p>你的邮箱:{userData.email}</p>
  </div>
)}

如上面的代码所示,使用标准方法可以在条件为false时正确地阻止访问userData的值。

我不确定为什么在使用带有children属性的自定义组件时会出现这种行为差异。我已经尝试过调试和寻找解决方案,但我还没有找到明确的答案。

非常感谢您提供的任何见解或建议,以解释可能发生的原因以及如何修改自定义组件以实现对children属性的预期条件渲染行为。

提前感谢您的帮助!

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

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号