【问题标题】:React: How do I only render a component on the page once I click on it from a mapped array?React:如何仅在从映射数组中单击组件后才在页面上呈现组件?
【发布时间】:2021-12-22 11:45:02
【问题描述】:

我有一个使用地图功能在页面上呈现的组件网格,我只想在单击它后呈现该组件及其所有详细信息,并且只设法得到一个错误提示:

Uncaught TypeError: Cannot read properties of undefined (reading 'logo')

我是 React 新手,不知道为什么会这样。

我们将不胜感激!

这是我的代码:

正文组件-(父组件)

import { useState } from "react";
import CompanyList from "./CompanyList";
import Company from "./Company";

const Body = ({ companies }) => {
  const [viewCompany, setViewCompany] = useState(false);
  const showCompanyHandler = (company) => {
    console.log("Clicked on company card");
    setViewCompany(true);
  };

  return (
    <div className="appBody">
      <CompanyList
        companies={companies}
        showCompanyHandler={showCompanyHandler}
      />
      {viewCompany && <Company />}
    </div>
  );
};

export default Body;

CompanyList 组件(Body 的子级)

import Company from "./Company";

const CompanyList = ({ companies, showCompanyHandler }) => {
  return (
    <div className="companyList">
      {companies.map((company) => (
        <Company
          key={company.id}
          company={company}
          showCompanyHandler={showCompanyHandler}
        />
      ))}
    </div>
  );
};

export default CompanyList;

公司组件(CompanyList 的子组件) - 我要在页面上显示的组件

const Company = ({ company, showCompanyHandler }) => {
  return (
    <div className="company" onClick={(company) => showCompanyHandler(company)}>
      {console.log(company)}
      <img src={company.logo} alt="logo" />
      <h1>{company.name}</h1>
      <p>{company.companyDescription}</p>
    </div>
  );
};

export default Company;

我不确定我在这里缺少什么......

【问题讨论】:

    标签: javascript reactjs components


    【解决方案1】:

    如果我理解正确,您的代码结构已损坏,您需要对其进行重构以实现您正在寻找的那种逻辑。

    首先,我建议您从 Body 组件中删除 {viewCompany &amp;&amp; &lt;Company /&gt;}viewCompanyshowCompanyHandler

    由于 Company 组件将始终可见,IMO 它应该负责处理您尝试实现的这种“扩展”逻辑,例如:

    const Company = ({ company }) => {
      const [showDetails, setShowDetails] = useState(false);
      const toggleShowDetails = () => setShowDetails(!showDetails);
      return (
        <div className="company" onClick={toggleShowDetails}>
          {showDetails &&
          <>
            <img src={company.logo} alt="logo" />
            <h1>{company.name}</h1>
            <p>{company.companyDescription}</p>
          </>
        }
          </div>
      );
    };
    
    export default Company;

    如您所见,通过此实现,您不再需要将 showCompanyHandler 传递给 Company 组件,您可以从 Body 组件中删除所有这些逻辑。

    【讨论】:

    • 感谢丹尼尔的回答。也许我在提出问题时不太清楚,但想法是,如果用户单击列表中的公司卡,它应该只在页面上呈现该公司,以及特定公司拥有的所有详细信息。如果您想切换公司视图,您的代码可以工作。还是谢谢
    • 不客气,安德烈!然后你可以尝试的是应用我建议但在CompanyList 组件中的这个逻辑!你绝对不能做的是渲染一个没有道具的Company 组件,就像你在Body 组件上尝试的那样。这可能会让您感到困惑,因为您刚刚学习 React,但这会呈现一个新的独立的 Company 组件,与您在 CompanyList 呈现的组件无关。
    • 感谢您帮我解决这个问题,Daniel,现在更有意义了。我收到错误是因为 Company 组件没有像我预期的那样获得任何道具。你认为我可以解决这个问题的一种方法是使用 React Router 并添加一个动态链接到 CompanyList 中呈现的 Company 组件吗?这可能会在页面上呈现正确的 Company 组件。
    • 如果你想在不同的路径上渲染公司组件,可以。您还可以使用全局状态(使用 React 的 Context 之类的东西)将公司数据传递给您的组件。如果 Company 仍然是 CompanyList 的子项,则您可以将当前公司数据作为道具传递。
    【解决方案2】:

    如果 CompanyList 组件工作正常,一个简单的方法是使用函数来动态生成列表,而不是直接引用该组件。

    import { useState } from "react";
    import CompanyList from "./CompanyList";
    import Company from "./Company";
    
    const Body = ({ companies }) => {
      const [viewCompany, setViewCompany] = useState(false);
    
      const showCompanyHandler = () => {
        console.log("Clicked on company card");
        setViewCompany(true);
      };
    
      // I removed the showCompanyHandler attribute and 
      // added an onClick to CompanyListContainer, instead.
      const generateCompanyList = (companies) => {
        if (viewCompany === false) return null;
        return <CompanyList companies={companies} />
        )
      }
    
      return (
        <div className="appBody">
          <CompanyListContainer onClick={showCompanyHandler}>
              {generateCompanyList}
          </CompanyList>
        </div>
      );
    };
    
    export default Body;
    

    如果 generateCompanyList 为 null,那么不幸的是,应该没有可点击的内容。因此,您可以在 div 中添加一些样式以获得最小宽度/高度,或者您可以将 onClick 移动到您的 appBody 组件。

    【讨论】:

      猜你喜欢
      • 2019-05-14
      • 2019-09-09
      • 2017-07-23
      • 2018-03-28
      • 2018-09-27
      • 1970-01-01
      • 1970-01-01
      • 2021-05-05
      • 1970-01-01
      相关资源
      最近更新 更多