I just learned react and I am building a simple blog app in react and I am trying to send props on button click But the props is not showing in the another functional component.
I am using react-bootstrap for modal (which is second component). And I am using for edit the current blog when user click on edit button in first component.
App.js
function SecondModalComponent(props) {
return (
<>
<Modal show={props.show}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>
<input type="text" value={props.title} />
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={props.onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
)
}
const response = [
{
title: "First Blog",
description: "First Blog"
},
{
title: "Second Blog",
description: "First Blog"
},
{
title: "Third Blog",
description: "First Blog"
}
]
function BlogFirstComponent() {
const [show, setShow] = useState(false);
const openEditModal = (title) => {
<SecondModalComponent
title={title}
/>
}
return (
<>
<SecondModalComponent
show={modalShow}
onHide={() => setShow(false)}
/>
{
response.map((data) =>
<div>
<b>Title</b> {data.title}
<b>Title</b> {data.description}
<span onClick={() => openEditModal(data.title)}>Edit</span>
</div>
)}
</>
)
}
I have tried many times but it is still no showing the prop title.
Any help would be much Appreciated.
this is not how react model works with UI component, component should be declarative, and not returned on a callback on click handler.
you can define your modal at the top level of your component
function BlogFirstComponent() {
const [secondModalOpen, setSecondModalOpen] = useState(false);
const [data, setData] = useState({ title: '', description: '' });
return (
<>
<SecondModalComponent
{...data}
show={secondModalOpen}
onHide={() => setSecondModalOpen(false)}
/>
...
{
response.map((data) =>
<div>
<b>Title</b> {data.title}
<b>Title</b> {data.description}
<span onClick={() => {
setData({...data});
setSecondModalOpen(true);
}>Edit</span>
</div>
)}
<>
);
}
Now, whenever someone clicks the button, the modal is opened, and the right props are passed to the component at that moment.
Related
I am working on a react-bootstrap-table, I set it up in a way when I click on the icon button, a modal pops up displaying the information of the row data. But when I click on another column of a row, the modal also pops up displaying data.
I want a situation whereby the modal only pops up when you click on the icon, instead of the row. This is making the cellEdit function not to be called.
const [modalInfo, setModalInfo] = useState([])
const [show, setShow] = useState(false);
const [showModal, setShowModal] = useState(null);
const rowEvents = {onClick: (e, row) => {
setModalInfo(row);
toggleTrueFalse();
},
};
const toggleTrueFalse = () => setShowModal(handleShow);
Cell Edit
const cellEdit = cellEditFactory({
mode: 'click',
blurToSave: true,})
Modal
const ModalContent = () => {
return (
<>
<Modal isOpen show={show}>
<ModalHeader>Terminal Info</ModalHeader>
<ModalBody>
<ul>
<h6 style={{ fontFamily: 'Georgia' }}>id : {modalInfo.id}</h6>
</ul>
</ModalBody>
<ModalFooter>
<Button color="secondary" onClick={handleClose}>
<FontAwesomeIcon icon="ban" />
Close
</Button>
</ModalFooter>
</Modal>
</>
);
};
jsx
return (
<>
<div>
<h2 style={{ color: "red", fontFamily: "Georgia" }}>Terminals</h2>
</div>
<BootstrapTable
keyField="id"
data={data}
columns={columns}
cellEdit={cellEdit}
rowEvents={rowEvents}
/>
{show ? <ModalContent /> : null}
</>
);
If I can be able to achieve this, then cellEdit will work fine.
getting this error:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
const MapBox = () => {
const mapContainer = useRef(null);
const map = useRef(null);
const [visible, setVisible] = useState(false)
const onClick = () => setVisible(true);
const closeHandler = () => {
setVisible(false);
}
useEffect(() => {
}, [visible])
return (
<>
<MapContainer ref={mapContainer} className="map-container" onClick={onClick}></MapContainer>
<ModalContainer visible={visible} closeHandler={closeHandler} />
</>
)
}
The modal container is just a simple modal pop, only returning a jsx component. That only shows if visible is true, and if runs closeHandler is a button is pressed.
const ModalContainer = ({ visible, closeHandler }) => {
useEffect(() => {}, [visible])
return (
<>
{visible && (
<div>
<Modal
closeButton
aria-labelledby="modal-title"
open={visible}
onClose={closeHandler}
>
<Modal.Header>
<Text id="modal-title" size={18}>
Welcome to
<Text b size={18}>
NextUI
</Text>
</Text>
</Modal.Header>
<Modal.Body>
<Input
clearable
bordered
fullWidth
color="primary"
size="large"
placeholder="Email"
/>
<Input
clearable
bordered
fullWidth
color="primary"
size="large"
placeholder="Password"
/>
<Row justify="space-between">
<Checkbox>
<Text size={14}>
Remember me
</Text>
</Checkbox>
<Text size={14}>
Forgot password?
</Text>
</Row>
</Modal.Body>
<Modal.Footer>
<Button auto flat color="error" onClick={closeHandler}>
Close
</Button>
<Button auto onClick={closeHandler}>
Sign in
</Button>
</Modal.Footer>
</Modal>
</div>)
}
</>
);
}
Any help would be much appreciated, all other people on here with this error message are running async code etc. This one is a lot simpler and the error only comes up the first time the click to close event happens.
I'm a begginer in React and I'm trying to find a way to dispatch a redux action from a modal.
I have a list of products and a button 'add to bag' under each image. When we click on the button 'add to bag', I want a modal to appear that ask for a confirmation. The action need to be dispatched when the user click on the confirm button inside de modal window.
The action need to grab the item object.
All is working fine ...but I'm not able to pass the item into the action when I want to launch the action from the modal.
So, my problem is not the Redux side but the modal part ( I use React-bootstrap for the modal).
I have this error message : 'item' is not defined
I'm not sure I understand exactly why this does'nt work and I failed to find a solution. I tried so many things but it's just not working.
Is there a simple way to add/pass the item data into the modal easily ?
Help would be very appreciated ! :)
Thanks a lot !!!
Here are part of my files :
Product.js
import { Modal } from "react-bootstrap";
function Products(props) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div>
<CardGroup>
{_.map(props.data, (item) => (
<Col>
...Some code here
<div>
<div>
{item.name.map((item) => (
<ul key={item}>{item}</ul>
))}
</div>
<div>
<button onClick={() => {handleShow()}}>
Add to bag
</button>
</div>
</div>
</Col>
))}
</CardGroup>
<Modal show={show} onHide={handleClose}>
<Modal.Body>Please confirm you want to add this product</Modal.Body>
<Modal.Footer>
<button
onClick={props.addProductToBasket(item)}
>
Confirm
</button>
<button onClick={handleClose}>Cancel</button>
</Modal.Footer>
</Modal>
</div>
);
}
const mapStateToProps = (state) => {
return { code here ...};
};
const mapDispatchToProps = (dispatch) => {
return {
addProductToBasket: (id) => dispatch(addProductToBasket(id)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Products);
Here is the part of my Product.js file im my Store/actions folder
export const addProductToBasket = (id) => {
return {
type: ADD_PRODUCTD_TO_BASKET,
payload: id,
};
};
Since you only show the modal if an item was clicked, store the item or null instead of Boolean in the state, and open and close the modal accordingly:
function Products(props) {
const [selectedItem, setShowItem] = useState(null); // item for open model or null for closed
const handleClose = () => setShowItem(null);
const handleShow = item => setShowItem(item);
return (
<div>
<CardGroup>
{_.map(props.data, (item) => (
<Col>
...Some code here
<div>
<div>
{item.name.map((item) => (
<ul key={item}>{item}</ul>
))}
</div>
<div>
<button onClick={() => handleShow(item)}>
Add to bag
</button>
</div>
</div>
</Col>
))}
</CardGroup>
<Modal show={selectedItem !== null} onHide={handleClose}>
<Modal.Body>Please confirm you want to add this product</Modal.Body>
<Modal.Footer>
<button
onClick={() => props.addProductToBasket(selectedItem)}
>
Confirm
</button>
<button onClick={handleClose}>Cancel</button>
</Modal.Footer>
</Modal>
</div>
);
}
Not related, but it will make your life easier - use the object form of mapDispatchToProps that will save you the need to wrap with dispatch manually:
const mapDispatchToProps = {
addProductToBasket
};
I am trying to play with react material ui dialog boxes and I noticed a problem or maybe I am doing it wrong. I've an object a and when I click on the a button in list, it should display the respective id number but it is always displaying the id number of the last id,index instead, what is the issue? Is it because i am calling them in a loop and all three dialogue boxes are being called at the same time? what should I do to basically show the respective id with every button.
...
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const a = [{ id: 1 }, { id: 2 }, { id: 3 }];
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<>
<List>
{a.map(({ id }, index) => {
return (
<>
<ListItem button onClick={handleClickOpen}>
{id}
</ListItem>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{id}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description" />
</DialogContent>
</Dialog>
</>
);
})}
</List>
</>
);
}
...
my sample https://codesandbox.io/s/material-demo-k5s8k?file=/demo.js
All 3 dialogs are being opened, because you are controlling all 3 of them using the same open variable. The last dialog is just the one on top. If you look at the DOM via the browser developer tools you will see that all 3 are there.
You can fix this by managing the open state in a way that allows you to tell which id is open.
One way is to set into state the id of the dialog that is open:
import React from "react";
import Dialog from "#material-ui/core/Dialog";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import DialogTitle from "#material-ui/core/DialogTitle";
import { List, ListItem } from "#material-ui/core";
export default function AlertDialog() {
const [openId, setOpenId] = React.useState(null);
const a = [{ id: 1 }, { id: 2 }, { id: 3 }];
const handleClickOpen = id => {
setOpenId(id);
};
const handleClose = () => {
setOpenId(null);
};
return (
<>
<List>
{a.map(({ id }, index) => {
return (
<>
<ListItem button onClick={() => handleClickOpen(id)}>
{id}
</ListItem>
<Dialog
open={openId === id}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{id}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description" />
</DialogContent>
</Dialog>
</>
);
})}
</List>
</>
);
}
I'm working on A React project with GraphQl back-end. I have a modal where a user can view more details about a subject. In that modal you can click delete which opens a new modal where you need to confirm if you wan't to delete. When yes is pressed it should be deleted and the modal should close. When no is pressed the modal should just close. The deleting of the subject works. If I press yes is deletes it but the modal doesn't close and when I press no the modal also doesn't close. Can anyone explain why and how I can fix this?
parent modal:
class CalenderModal extends React.Component {
constructor(props) {
super(props);
this.state = {
openDeleteAppointment: false,
};
this.openDeleteAppointment = this.openDeleteAppointment.bind(this);
}
handleRemove = () => {
this.props.onRemove();
}
openDeleteAppointment() {
this.setState({
openDeleteAppointment: true,
})
}
render() {
return (
<React.Fragment>
<div className="customModal">
<div className="modal-header">
<h5 className="customModal__text"> Appointment summary</h5>
<button className="btn modal__button__red" onClick={() => { this.openDeleteAppointment() }}>Delete</button>
{this.state.openDeleteAppointment &&
<DeleteAppointmentModal appointment={this.state.id} onHide={() => this.setState({ openDeleteClient: false, id: null })} show />}
</div>
<div className="modal-container">
<div className="summary">
<button className="btn modal__button__cancel" onClick={this.handleRemove}>Cancel</button>
</div>
</div>
}
</React.Fragment>
);
}
export default CalenderModal;
child modal:
class DeleteAppointmentModal extends React.Component {
constructor(props) {
super(props);
this.state = {
id: this.props.appointment,
};
}
render() {
const {id} = this.state
const DELETE_MUTATION = gql`
mutation DeleteMutation($id:ID! ) {
deleteAppointment(id:$id) {
id
}
}
`
console.log("delete id",this.state.id)
return (
<React.Fragment>
{
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-update-client"
centered
>
<Modal.Header closeButton >
<Modal.Title id="contained-modal-title-vcenter" className="tittle">Delete appointment </Modal.Title>
</Modal.Header>
<Modal.Body>
<div className="delete-content">
Are you sure you want to delete this appointment?
</div>
</Modal.Body>
<Modal.Footer>
<button onClick={() => this.props.onHide() } className="btn no">No</button>
<Mutation mutation={DELETE_MUTATION}
variables={{id}}>
{/* onCompleted={() => this.props.history.push('/')} */}
{deleteMutation =>
<button onClick={() => { deleteMutation(); this.props.onHide() }} className="btn yes">Yes</button>
}
</Mutation>
</Modal.Footer>
</Modal>
}
</React.Fragment>
);
}
}
export default DeleteAppointmentModal;
On "return" of parent component change the following row:
from:
<DeleteAppointmentModal appointment={this.state.id} onHide={() => this.setState({ openDeleteClient: false, id: null })} show />}
to:
<DeleteAppointmentModal appointment={this.state.id} onHide={() => { this.setState({ openDeleteAppointment: false, id: null }); handleRemove(); }} show />}
Hope it solved the problem.
From observation:
the show prop is always true. set show={this.state. openDeleteAppointment}
the onHide is not setting the right state. it should set openDeleteAppointment instead of openDeleteClient