Reputation: 103
Hi there,
The issue that I faced recently is the next:
I have a parent component MainPage
, that has child components ModalJoin
(is not shown by default) and ExploreProjects
in it. This ExploreProjects
component has its own child component ProjectCard
which has a button that is supposed to change a state so ModalJoin
is shown.
Does anyone have a solution of how do I bind all these, so when the button is clicked ->useState changes to true and ModalJoin
pops up? Been trying to link them properly the whole day but still didn't find a solution.
Would appreciate any help!
Have the following files:
Main page
import React, {useState} from 'react'
import ExploreProjects from './ExploreProjects'
import ModalJoin from './ModalJoin'
export default function MainPage() {
const [isOpened, setIsOpened] = useState(false)
return (
<div>
<div className='app'>
<div className="app__body">
<ExploreProjects/>
</div>
</div>
<ModalJoin openModal={isOpened} onClose={() => setIsOpened(false)}/>
</div>
)
}
ExploreProjects
import React from 'react'
import './ExploreProjects.css'
import ProjectCard from './ProjectCard'
function ExploreProjects() {
return (
<div className='explore__projects'>
<div className="filters__section">
<div className='filter__item'>
<h3>Location</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
<div className='filter__item'>
<h3>Industry</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
<div className='filter__item'>
<h3>Company</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
<div className='filter__item'>
<h3>Complexity</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
<div className='filter__item'>
<h3>Duration</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
</div>
<div className="projects__section">
<ProjectCard />
<ProjectCard />
<ProjectCard />
<ProjectCard />
<ProjectCard />
<ProjectCard />
</div>
</div>
)
}
export default ExploreProjects
ProjectCard
import React, {useState} from 'react'
import './ProjectCard.scss'
export default function ProjectCard({ src, logo, headline, companyName,
complexity, description, projectType, tag }) {
const [setIsOpened] = useState(false)
return (
<div className='project__card'>
<div className="project__card__header">
<img src="/images/rehauIcon.png" alt="" className='company__logo' />
<h3>Logistics Project</h3>
<div className="project__card__company">
<img src="/images/buildingIcon.svg" alt="" />
<p>Rehau</p>
<p>/</p>
<img src="/images/locationIcon.svg" alt="" />
<p>Berlin</p>
</div>
<div className="project__card__complexity">
<div className="basic__complexity"></div>
<p>Basic</p>
</div>
</div>
<div className="project__card__body">
<div>
<h3>Task:</h3>
</div>
<span>Text
<button>More</button>
</span>
</div>
<div className="project__card__bottom">
<div className="project__card__time">
<p>15m ago</p>
</div>
<div className="project__card__recruitment">
<p>Job opportunity</p>
</div>
<div className="project__card__teams">
<p>1/2 teams joined</p>
</div>
<div className="project__card__tag">
<p>#supplychain</p>
</div>
</div>
<div className="project__card__right">
<img src="images/imgHero.png" alt="" className='project__video__info' />
<div onClick={ () => this.setIsOpened(true)} className="join__project__button">
<p>Join</p>
</div>
</div>
</div>
)
}
ModalJoin
import React from 'react'
export default function ModalJoin({openModal, onClose}) {
if (!openModal) return null
return (
<div>
<button onClick={onClose}>Close</button>
HEEEYYYYYY
</div>
)
}
Upvotes: 2
Views: 135
Reputation:
Lets go with a simple example on how to change state of a parent from a child and manipulate conditional rendering. you have to pass setState to the child and subChild as well and call it from there. That changes parent state and reflects on modal.
Code Sandbox => https://codesandbox.io/s/silent-bush-c6v4d?file=/src/App.js:0-992
Here you go, this should fix your issue.
import React, { useState } from "react";
import "./styles.css";
const ModalJoin = ({ open, close }) => {
const modal = open ? (
<div style={{ background: "pink" }}>
I am ModalJoin
<button onClick = {close}> Close Me</button>
</div>
) : null;
return modal;
};
const ExploreProjects = ({ click }) => {
return (
<div style={{ background: "orange" }}>
I am ExploreProjects
<ProjectCard click={click} />
</div>
);
};
const ProjectCard = ({ click }) => {
return (
<div style={{ background: "grey" }}>
I am ProjectCard
<button onClick={click}>click me to open modal </button>
</div>
);
};
const App = () =>
{
const [modal, setModal] = useState(false)
return (
<div className="App" style={{ background: "lightBlue" }}>
<h1>I am Parent</h1>
<ExploreProjects click = {() => setModal(true)}/>
<ModalJoin open={modal} close={() => setModal(false)} />
</div>
);
};
export default App;
Upvotes: 1
Reputation: 13892
I commented:
You'll need to pass a callback prop down
<ExploreProjects onOpenModalJoin={callback} />
, and then pass the same callback down from ExploreProjects down to ProjectCard. Then in project card on the button click, you would call that callback.
This is a more full explanation:
export default function MainPage() {
const [isOpened, setIsOpened] = useState(false);
const callback = () => setIsOpened(true);
...
<ExploreProjects onOpenModalJoin={callback} />
function ExploreProjects(props) {
...
<ProjectCard onOpenModalJoin={props.onOpenModalJoin} />
...
And then inside ProjectCard, you would have
onClick={props.onOpenModalJoin}
Upvotes: 1