The site has a button for deleting an element (one element is deleted per button click).
Timing: the user presses the delete button -> a window opens with a warning and two buttons: cancel and confirm -> when the confirm button is pressed, the deletion process begins, which is accompanied by a scroll wheel. After deletion, the window closes and you can continue to work on the site.
I would like to display a notification after the window is closed that the item was removed successfully. Tell me how can I do it.
export function Delete() {
const [alertShown, setAlertShown] = useState(false);
const [alertLoading, setAlertLoading] = useState(false);
const onNo = () => {
setAlertShown(false);
};
const onYes = async () => {
setAlertLoading(true);
await deleteItem();
setAlertShown(false);
setAlertLoading(false);
};
return <ButtonGroup >
<div onClick={() => setAlertShown(true)}>
<DeleteForeverIcon/>
</div>
{alertShown && (
<Dialog open={onYes}>
{alertLoading
? <div ><Spinner/></div>
: <DialogActions >
<Button color="error" onClick={onNo}>Cancel</Button >
<Button onClick={onYes}>Confirm </Button >
</DialogActions>}
</Dialog>
)}
</ButtonGroup>
}
The easiest approach to implement notification is using setTimeout. You can try the below code snippet
export function Delete() {
const [alertShown, setAlertShown] = useState(false);
const [alertLoading, setAlertLoading] = useState(false);
const [notificationShown, setNotificationShown] = useState(false);
const onNo = () => {
setAlertShown(false);
};
const onYes = async () => {
setAlertLoading(true);
await deleteItem();
setAlertShown(false);
setAlertLoading(false);
//open the notification
setNotificationShown(true);
setTimeout(() => {
setNotificationShown(false);
}, 5000); //automatically close the notification after 5 seconds
};
return (
<ButtonGroup>
{notificationShown && <span>The item was removed successfully</span>}
<div onClick={() => setAlertShown(true)}>
<DeleteForeverIcon />
</div>
{alertShown && (
<Dialog open={onYes}>
{alertLoading ? (
<div>
<Spinner />
</div>
) : (
<DialogActions>
<Button color="error" onClick={onNo}>
Cancel
</Button>
<Button onClick={onYes}>Confirm </Button>
</DialogActions>
)}
</Dialog>
)}
</ButtonGroup>
);
}
The sandbox link
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.
I would like to create a custom button component that shows a loading spinner within itself when it's pressed and with a condition that can be externally defined which will tell the button to remove the spinner and return to its original appearance. Something like this:
<CustomButton
type="button"
className="btn btn-primary"
stopSpinningWhen={condition}
onClick={() => ...}
>
Click me
</CustomButton>
Currently, my buttons with a spinner look like this, which is super fine, but it's a pain to write repetitive code/states for each single button:
const [buttonSpinner, setButtonSpinner] = useState(false);
const onClickEvent = (ev) => {
setButtonSpinner(true);
if (condition) {
setButtonSpinner(false);
}
};
return (
<button
type="button"
className="btn btn-primary"
onClick={onClickEvent}
disabled={buttonSpinner}
>
{buttonSpinner ? (
<span
className="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
></span>
) : (
"Click me"
)}
</button>
);
I'm using React 17.0.2.
Is it even possible?
You can create your own custom button that receives isLoading additionally.
const Spinner = (
<span
className="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
/>
)
const CustomButton = (props) => (
<button
type="button"
className="btn btn-primary"
onClick={props.onClick}
disabled={props.isLoading}
>
{props.isLoading ? <Spinner /> : "Click me"}
</button>
)
const YourComponent = () => {
const [isLoading, setIsLoading] = useState(false)
const onClick = async (event) => {
setIsLoading(true)
doHeavyTask()
setIsLoading(false)
}
return (
<div>
<CustomButton isLoading={isLoading} onClick={onClick} />
</div>
)
}
You use a loading property as your condition and just pass that as a prop to your custom button component. Something like this:
const myComponent = () =>{
const [loading, setLoading] = useState(false)
const myFunc = async () = {
setLoading(true)
//call api or do seomthing, after the process finishes set loading to false again
const resp = await fetch("myAPIURL")
console.log(resp.data)
setLoading(false)
}
return(
<CustomButton
type="button"
className="btn btn-primary"
spinning={loading}
onClick={() => myFunc()}
>
Click me
</CustomButton>
)
}
I am intern ReactJs, how to use multiple-drawer reactJs in same page.
code my App.js file
App = () =>{
const [visible, setVisible] = useState(false);
const showDrawer = () => {
setVisible(true);
};
const onClose = () => {
setVisible(false);
};
return(
// drawer 1
<Button type="primary" className="btn-submit" onClick={this.showDrawer}>submit drawer 1</Button>
<Drawer className="modal-form"onClose={onClose} visible={visible}>
content
</Drawer>
// drawer 2
<Button type="primary" className="btn-submit" onClick={this.showDrawer}>submit drawer 2</Button>
<Drawer className="modal-form"onClose={onClose} visible={visible}>
content
</Drawer>
)
}
how can i click on the button tag to show the corresponding drawer!
pls! help me.
If these drawers contain different content then you will have to manage two state variables for each drawer to control the visibility of drawer.
App = () =>{
const [visibleDrawer1, setVisibleDrawer1] = useState(false);
const [visibleDrawer2, setVisibleDrawer2] = useState(false);
const showDrawer1 = () => {
setVisibleDrawer1(true);
};
const onCloseDrawer1 = () => {
setVisibleDrawer1(false);
};
const showDrawer2 = () => {
setVisibleDrawer2(true);
};
const onCloseDrawer2 = () => {
setVisibleDrawer2(false);
};
return(
// drawer 1
<Button type="primary" className="btn-submit"
onClick={this.showDrawer1}>submit drawer 1</Button>
<Drawer className="modal-form"onClose={onCloseDrawer1}
visible={visibleDrawer1}>
content
</Drawer>
// drawer 2
<Button type="primary" className="btn-submit"
onClick={this.showDrawer2}>submit drawer 2</Button>
<Drawer className="modal-form"onClose={onCloseDrawer2}
visible={visibleDrawer2}>
content
</Drawer>
)
}
I am trying to render a button in a react-table column. If I refactor the button to its own component, it complains that it's not a function.
Top level (ExampleReactTable.js):
const handleClick = () => setIsOpen(true);
const columns = getTableColumns(handleClick);
Middle layer (getTableColumns.js):
Cell: () => <ExampleButton handleClick={() => handleClick()} />
Botton layer (ExampleButton.js):
const ExampleButton = handleClick => {
console.log(handleClick);
return (
<Box>
<Button variation="text" onClick={() => handleClick()}>
Click
</Button>
</Box>
);
};
This errors out with handleClick is not a function.
If I don't refactor the button out, it works:
Cell: () => (
<Box>
<Button variation="text" onClick={() => handleClick()}>
Click
</Button>
</Box>)
You are not destructuring props, because the function received the props as an object, which you are passing to onclick as a function, resulting in the error, try this:
const ExampleButton = ({handleClick}) => {
console.log(handleClick);
return (
<Box>
<Button variation="text" onClick={() => handleClick()}>
Click
</Button>
</Box>
);
};
This is the same as:
const ExampleButton = (props) => {
console.log(handleClick);
return (
<Box>
<Button variation="text" onClick={() => props.handleClick()}>
Click
</Button>
</Box>
);
};
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
};