I would like to add a popup form in each item in the Flatlist, and the item is actually a card.
My problem is that every time, I clicked the button, the popup shows but, when my mouse moves out of the card, instead of showing the original one, it shows another popup whose parent is the whole page.
I know the problem should be that I need not set the variable setPopup properly. But I don't know how to fix it.
When my mouse is on the card:
enter image description here
When my mouse is out of the card, the popup will move up and its position will be based on the whole page:
enter image description here
Thank you!
This is my code.
const [buttonPopUp, setButtonPopUp] = useState(undefined);
const renderItem = (item, index) => {
return(
<Card key={index} style={{width: '20rem'}}>
<CardImg className='galleryPics' top src={galleryPic.img} alt="..."/>
<CardBody>
<PopUpEditGallery
gallery={item}
index = {index}
trigger={buttonPopUp}
setTrigger={setButtonPopUp}
>
Edit
</PopUpEditGallery>
<CardTitle className='cardTitle'>{item.title}</CardTitle>
<CardText className='cardText'>{item.description}</CardText>
<Button className="btn-round btn-icon" color="primary" size='sm' onClick={()=> setButtonPopUp(index)}>Edit</Button>
</CardBody>
</Card>
);
}
return (
<div>
<div>
<Header/>
</div>
<div className="container">
<div className="row">
<div className='col-7'>
<ul>
<FlatList
list={values.gallery}
renderItem={renderItem}/>
</ul>
</div>
</div>
</div>
</div>
)
code for popup
return (props.trigger != undefined) ? (
props.trigger == props.index &&
<div className='popup'>
<div className='popupInner'>
<form onSubmit={handleSubmit(onSubmit)}>
<FormGroup>
<Label>Title</Label>
<Input
type="text"
placeholder={prev.title}
onChange={val => props.setTitle(val.target.value, prev.idx)}
/>
</FormGroup>
<Button className="btn-round btn-icon" color="primary" size='sm'>
Submit
</Button>
<Button className="btn-round btn-icon" color="default" size='sm'>
Cancel
</Button>
</form>
</div>
</div>
): "";
For example, i have this functon that returns to me some ids and i get delete this posts with the id's returned with: onClick={() => { Delete(idvalue[i]) }}
However I need to open a modal before deleting the item asking if the person is sure they want to delete, and when they click on the yes I have no idea how to pass the right value to delete and where will stay this onClick to open the modal.
function Idchecker() {
for (let i = 0; i < idvalue.length; i++) {
if (idvalue[i] == item.id) {
return (
<div className="img-array">
<button className="click-img" onClick={() => { Delete(idvalue[i]) }}>
<img src={trash} alt="botão excluir" className="imgsbtns" />
</button>
<button className="click-img">
<img src={edit} alt="botão editar" className="imgsbtns" />
</button>
</div>
)
}
}
}
the modal:
return (
<Modal
{...props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
style={{ fontFamily: "Questrial" }}
>
<Modal.Header>
<Modal.Title id="contained-modal-title-vcenter">
DELETE THE POST
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>
are you sure?
</p>
<Button onClick={Delete}>YES</Button>
</Modal.Body>
<Modal.Footer>
<Button onClick={props.onHide}>CLOSE</Button>
</Modal.Footer>
</Modal>
);
}
Add two state:
openDeleteModal to manage opening modal (argument for example, you have this argument yet)
deleteId to store id.
const [openDeleteModal, setOpenDeleteModal] = useState(false);
const [deleteId, setDeleteId] = useState(null);
When you click on post you must open modal and update deleteId, so rewrite onClick function:
onClick={()=>{
setDeleteId(idvalue[i]);
setOpenDeleteModal(true)}
}
Pass deleteId and setOpenModal via props to Modal component and rewrite modal buttons function:
<Modal.Body>
<p>
are you sure?
</p>
<Button
onClick={()=>{
Delete(deleteId)
setOpenDeleteModal(false) //close modal after delete
}}>
YES
</Button>
</Modal.Body>
<Modal.Footer>
<Button onClick={()=>setOpenDeleteModal(false)}>CLOSE</Button>
</Modal.Footer>
I am using Reactstrap to open and collapse multiple cards. Once opened, they stay open, and since I plan to use more of them (for articles), this will be a mess. Once I click on a button and open a card, I would like the others to close, so only one card is displayed at a time. How can I achieve this?
const [isOpenInfo, setIsOpenInfo] = useState(false);
const toggleInfo = () => setIsOpenInfo(!isOpenInfo);
const [isOpenArticle1, setIsOpenArticle1] = useState(false);
const toggleArticle1 = () => setIsOpenArticle1(!isOpenArticle1);
const [isOpenArticle2, setIsOpenArticle2] = useState(false);
const toggleArticle2 = () => setIsOpenArticle2(!isOpenArticle2);
In my menu, I have a button "More Info", when clicked, it opens a list of collapsed articles and when clicking on each title, it opens the article (but I just want one article to open at a time). So it's like a collapse inside a collapse...
<Button className="info-button" color="primary" onClick={toggleInfo}>
More Info
</Button>
<Collapse isOpen={isOpenInfo}>
<Card className="card">
<CardBody className="card-body">
<div className="section section-articles">
<div className="articles-buttons">
<Button
className="article2-button"
color="primary"
onClick={toggleArticle2}
>
<h3>Article 2</h3>
</Button>
<Button
className="article1-button"
color="primary"
onClick={toggleArticle1}
>
<h3>Article 1</h3>
</Button>
</div>
<Collapse isOpen={isOpenArticle2}>
<Card className="card">
<CardBody className="card-body">
<Article2 />
</CardBody>
</Card>
</Collapse>
<Collapse isOpen={isOpenArticle1}>
<Card className="card">
<CardBody className="card-body">
<Article1 />
</CardBody>
</Card>
</Collapse>
</div>
</CardBody>
</Card>
</Collapse>
You can create a default variable consisting all your articles and use it to set the state. Create a single state variable for all of your collapsible.
const DEFAULT_ARTICLES = {
article1: false,
article2: false,
};
const [articles, setArticles] = useState(DEFAULT_ARTICLES);
const toggleArticle = (key) => setArticles({
...DEFAULT_ARTICLES,
[key]: true,
});
And on your render function use the key to open the collapse and toggle the collapse.
<Collapse isOpen={isOpenInfo}>
<Card className="card">
<CardBody className="card-body">
<div className="section section-articles">
<div class="articles-buttons">
<Button
className="article2-button"
color="primary"
onClick={() => toggleArticle('article2')}
>
<h3>Article 2</h3>
</Button>
<Button
className="article1-button"
color="primary"
onClick={() => toggleArticle('article1')}
>
<h3>Article 1</h3>
</Button>
</div>
<Collapse isOpen={articles['article1']}>
<Card className="card">
<CardBody className="card-body">
<Article2 />
</CardBody>
</Card>
</Collapse>
<Collapse isOpen={articles['article2']}>
<Card className="card">
<CardBody className="card-body">
<Article1 />
</CardBody>
</Card>
</Collapse>
</div>
</CardBody>
</Card>
</Collapse>
You can use one state to control all the collapses.
const [openedCollapse, setOpenedCollapse] = useState("");
const openCollapse = e => { // this is the button onClick handler
setOpenedCollapse(e.target.dataset.collapse);
};
Then your jsx looks like this:
<Button
className="article1-button"
color="primary"
data-collapse="article1" // A dataset param
onClick={openCollapse}>
<h3>Article 1</h3>
</Button>
<Collapse isOpen={openedCollapse === "article1"}>
<Card className="card">
<CardBody className="card-body">
<Article2 />
</CardBody>
</Card>
</Collapse>
dataset info
You can use an object as state with a callback function when toggling the More Info collapse and then utilize a simple string to determine which article should be opened when the main Collapse is open and a Button was clicked inside of it.
For example, updating whether or not the main collapse is open:
const toggleMoreInfo = () => {
setState(prevState => {
// this gives us access to the current state when setState is executed
// then we can inverse a boolean when the More Info button is clicked
return {
article: "", // resets the open article
moreInfoOpen: !prevState.moreInfoOpen // false => true || true => false
}
})
}
For example, updating which article should be opened:
const handleArticleOpen = (article) => {
setState((prevState) =>
return {
// keep whatever is in state as is by spreading it out (in this case, "moreInfoOpen" stays unchanged)
...prevState, //
// and just override the article with a passed in string
article
}));
};
When dealing with coupled state, I like to use objects over individual states, since it's easier to keep both sets of state in sync. For a demo and the full code, look below...
Working demo:
Code
import * as React from "react";
import { Button, Card, CardBody, Collapse } from "reactstrap";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
export default function App() {
const [state, setState] = React.useState({
articleOpen: "",
moreInfoOpen: false
});
const { article, moreInfoOpen } = state;
const toggleMoreInfo = () => {
setState((prevState) => ({
article: "",
moreInfoOpen: !prevState.moreInfoOpen
}));
};
const handleArticleOpen = (article) => {
setState((prevState) => ({
...prevState,
article
}));
};
return (
<div className="app">
<Button className="info-button" color="primary" onClick={toggleMoreInfo}>
More Info
</Button>
<Collapse isOpen={moreInfoOpen}>
<Card className="card">
<CardBody className="card-body">
<div className="section section-articles">
<div className="articles-buttons">
<Button
className="article2-button"
color="primary"
onClick={() => handleArticleOpen("2")}
>
<h3>Article 2</h3>
</Button>
<Button
className="article1-button"
color="primary"
onClick={() => handleArticleOpen("1")}
>
<h3>Article 1</h3>
</Button>
</div>
<Collapse isOpen={article === "2"}>
<Card className="card">
<CardBody className="card-body">
<div>Article 2</div>
</CardBody>
</Card>
</Collapse>
<Collapse isOpen={article === "1"}>
<Card className="card">
<CardBody className="card-body">
<div>Article 1</div>
</CardBody>
</Card>
</Collapse>
</div>
</CardBody>
</Card>
</Collapse>
</div>
);
}
I'm using Material UI for the icons for connect and disconnect.
I want the application to swap between these two icons onClick.
I'm new to React, but haven't any helpful resources yet.
Here's the code as it is so far:
{ user.connected ?
(
<Button color="info" simple size="sm">
<PersonAddDisabled className={classes.footerIcons} /> Disconnect
</Button>
)
:
(
<Button color="info" size="sm">
<PersonAdd className={classes.footerIcons} /> Connect
</Button>
)
}
As it is above, I am address whether they are connected or not, but I'm not sure how to implement a toggle of those two buttons, where onClick it will switch between the two.
here is a code
Your state
state = {
connected: true
}
onClickButton(){
this.setState(prevState => {connected: !this.prevState.connected})
}
Your code
{ this.state.connected ?
(
<Button color="info" simple size="sm" onClick={ this.onClickButton }>
<PersonAddDisabled className={ classes.footerIcons } /> Disconnect
</Button>
)
:
(
<Button color="info" size="sm" onClick={ this.onClickButton }>
<PersonAdd className={ classes.footerIcons } /> Connect
</Button>
)
}
I'm having trouble with the reactstrap modals. I'm looping through an array and it makes modals and buttons, and gets information in a nice card.
Now when I click on a button to open the modal, all modals open even if I didn't click the button on the card. All (39) open. I was hoping you all could help me out <3
Modal State
this.state= {
modal:false,
}
Toggle Function
toggle(){
this.setState(prevState =>({
modal: !prevState.modal
}));
}
Everything that gets returned
return (
<div key={item.ID}>
<ul>
<Modal isOpen={this.state.modal} toggle={this.modal} id={item.ID}>
<ModalHeader id={item.ID} toggle={this.toggle}>{item.Naam}</ModalHeader>
<ModalBody>fdass</ModalBody>
<ModalFooter><Button onClick={this.toggle} color='primary'>fddss</Button></ModalFooter>
</Modal>
<Card style={{ width: '18rem' }}>
{/* <CardImg src={"http://static.floraxchange.nl/artikelen/"+ item.Fotos.ID +"_v_t8.jpg"} alt={item.Naam} /> */}
<Card.Body>
<Card.Title>{item.Naam}</Card.Title>
<Card.Text>
Hoogte: {item.Hoogte}<br />
Potmaat: {item.Potmaat} <br/>
ID: {item.ID}
</Card.Text>
<Button color="danger" data-target={'#' + item.ID} onClick={this.toggle}>More information</Button>
</Card.Body>
</Card>
</ul>
</div>
)