开发者问题收集

React:如何仅在从映射数组中单击该组件后才在页面上渲染该组件?

2021-11-09
1126

我使用 map 函数在页面上渲染了一个组件网格,我只想在单击该组件后渲染其所有详细信息,但只会出现错误提示:

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

我是 React 新手,不知道为什么会发生这种情况。

如能得到帮助将不胜感激!

这是我的代码:

Body 组件 - (父组件)

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;

Company 组件 (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;

我不确定这里遗漏了什么……

2个回答

如果我理解正确的话,您的代码结构已损坏,您需要重构它以实现所需的逻辑类型。

首先,我建议您从 Body 组件中删除此 {viewCompany && <Company />>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 组件中删除所有这些逻辑。

Daniel Baldi
2021-11-09

如果 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 组件。

James
2021-11-09