Tengo una cuadrícula de componentes representados en una página usando la función de mapa y solo quiero representar el componente con todos sus detalles una vez que hago clic en él y solo obtengo un error que dice:
TypeError no capturado: no se pueden leer las propiedades de undefined (leyendo 'logo')
Soy nuevo en React y no puedo entender por qué sucede esto.
¡Alguna ayuda sería muy apreciada!
Aquí está mi código:
Componente del cuerpo - (componente principal)
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;Componente CompanyList (hijo de 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;Componente de empresa (hijo de CompanyList) - Componente que quiero mostrar en la página
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;No estoy seguro de lo que me estoy perdiendo aquí...
Si el componente CompanyList funciona bien, una forma fácil de hacerlo sería usar una función para generar dinámicamente la lista en lugar de tener una referencia directa al componente.
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;Si generarCompanyList es nulo, lamentablemente no debería haber nada en lo que hacer clic. Por lo tanto, puede agregarle algunos estilos al div para un ancho/alto mínimo, o puede mover eso onClick a su componente appBody.
Si entendí correctamente, la estructura de su código está rota y necesita refactorizarla para implementar el tipo de lógica que está buscando.
En primer lugar, le sugiero que elimine este {viewCompany && <Company />} , viewCompany y showCompanyHandler de su componente Body.
Dado que el componente Company siempre estará visible, en mi opinión, debería ser responsable de manejar esta lógica de "expansión" que está tratando de implementar, algo como:
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; Como puede ver, con esta implementación ya no tiene que pasar showCompanyHandler al componente Company y puede eliminar toda esta lógica del componente Body.