I have a toast notification created using react-bootstrap. I need to dismiss it if the user clicks anywhere outside the toast. Someone knows how can I do that?
This is the toast I'm using:
//what am I importing
import { Toast } from 'react-bootstrap';
//how am I using it
<Toast
onClose={() => props.OnClose(false)}
data-testid="toast"
show={props.Show}
delay={10000}
autohide
>
<Toast.Header closeButton={false}>
<div>
{props.Icon}
</div>
<div>
Title
</div>
<div
onClick={() => props.OnClose(false)}
>
<ToastClose />
</div>
</Toast.Header>
<Toast.Body>
Body text
</Toast.Body>
</Toast>
What you can use is React hook useRef. Using useRef hook we can access the DOM elements easily and in this case we are accessing the Toast component and tracking clicks that happen outside of the component and firing the setShow(false) to update the state and dismiss the Toast component. This code will dismiss the Toast if the user clicks anywhere outside of it:
import { Toast } from "react-bootstrap";
import { useState, useRef, useEffect } from "react";
export default function App() {
const [show, setShow] = useState(true);
function useOutsideAlerter(ref) {
useEffect(() => {
/**
* Close toast if clicked on outside of element
*/
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
setShow(false);
}
}
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
}
const wrapperRef = useRef(null);
useOutsideAlerter(wrapperRef);
return (
<div className="App">
<Toast
onClose={() => setShow(false)}
data-testid="toast"
show={show}
delay={10000}
autohide
ref={wrapperRef}
>
<Toast.Header closeButton={false}>
<div>Toast title</div>
<div onClick={() => setShow(false)}>Close button</div>
</Toast.Header>
<Toast.Body>Body text</Toast.Body>
</Toast>
</div>
);
}
Original post with more info: link
Related
In ionic framework when the hardware back button is pressed the following event listener method is executed.
document.addEventListener('ionBackButton', (ev) => {
ev.detail.register(10, () => {
console.log('Handler was called!');
});
});
But when a modal kept opened then the above method is not executed after pressing the hardware back button. It shows only the following message on the console of android studio
Notifying listeners for event backButton
Updated :
the following code is for the modal in ionic react
import React, { useState } from 'react';
import { IonModal, IonButton, IonContent } from '#ionic/react';
export const ModalExample: React.FC = () => {
const [showModal, setShowModal] = useState(false);
return (
<IonContent>
<IonModal isOpen={showModal} cssClass='my-custom-class'>
<p>This is modal content</p>
<IonButton onClick={() => setShowModal(false)}>Close Modal</IonButton>
</IonModal>
<IonButton onClick={() => setShowModal(true)}>Show Modal</IonButton>
</IonContent>
);
};
I have found the solution for triggering the hardware back button event listener method, simply by increasing the priority up to 140.
document.addEventListener('ionBackButton', (ev) => {
ev.detail.register(140, () => {
console.log('Handler was called!');
});
});
I am trying to toggle true/false in my component using useState but I've noticed it only toggles one time and does not go back and forth. On clicking the component, it toggles true but then it won't toggle back to false. Any ideas on how to solve?
const [sound, setSound] = useState(false);
return (
<div>
<ReactPlayer
...
muted={sound}
onClick={() => {
setSound(!sound);
console.log("on click", sound);
}}
/>
</div>
)
EDIT
Thanks for the replies, I think the issue was the anon function, I solved it by doing this
onClick={() => {
setSound((sound) => !sound);
console.log("on click", sound);
}}
import React, {useState} from 'react';
import './App.css';
const ReactPlayer = ({muted, onClick}: {muted: boolean, onClick: () => any}) => {
return (
<div>
<button onClick={onClick}>Test</button>
<p>{muted.toString()}</p>
</div>
)
}
function App() {
const [sound, setSound] = useState(false);
return (
<div className="App">
<ReactPlayer
muted={sound}
onClick={() => {
setSound(!sound);
console.log("on click", sound);
}}
/>
</div>
);
}
export default App;
This code works perfectly, I don't know what you have in your ReactPlayer component, but this should work
As of Chrome 66, videos must be muted in order to play automatically. Some players, like Facebook, cannot be unmuted until the user interacts with the video, so you may want to enable controls to allow users to unmute videos themselves. Please set muted={true}. see docs for more info
Check the live code here in sandbox link
import ReactPlayer from "react-player";
import React, { useState } from "react";
// Render a YouTube video player
export default function App() {
const [play, setPlay] = useState(true);
return (
<div className="App">
<ReactPlayer
muted={play}
url="https://www.youtube.com/watch?v=9DDX3US3kss"
/>
Click to Mute or Unmute --
<button style={{ margin: "15px" }} onClick={() => setPlay(!play)}>
Mute/UnMute
</button>
</div>
);
}
I've only been working with React.js for a month or so and I hope someone can point me towards my errors so I can learn more.
I've created a reusable button component, but during testing, while the button displays correctly and I can change the value correctly - the onClick function is not working. Right now, I am trying to get the button to redirect onClick to the first path.
Below I have added the relevant areas of my code and hope someone can assist.
Display component:
import Sidebar from '../../Components/SideNav/Sidebar'
import GenButton from '../../Components/Buttons/GenButton'
export default function Sales({ authorized }) {
let history = useHistory();
const handleRoute = () =>{
history.push("/")
}
if (!authorized) {
return <Redirect to='/' />
}
return (
<div>
<Sidebar />
<div className='content'>
<h2>Sales Page</h2>
<GenButton
value="Home"
onClick={handleRoute}
/>
</div>
</div>
)
}
GenButton code:
import React from 'react'
import './GenButton.css';
const GenButton = ({value, onClick}) => {
return <button className='btn' onClick={() => onClick}>
{value}
</button>
}
export default GenButton
I need to understand more about why this isn't working, as multiple components I need to create will have between 2-4 buttons that need to route towards other pages or events.
Thank you for your assistance.
Because onClick is a function inside your Gen Button component you need to call it as a function.
import React from 'react'
import './GenButton.css';
const GenButton = ({value, onClick = () => {}}) => {
return <button className='btn' onClick={() => onClick()}>
{value}
</button>
or just
import React from 'react'
import './GenButton.css';
const GenButton = ({value, onClick = () => {}}) => {
return <button className='btn' onClick={onClick}>
{value}
</button>
I added a default value to onClick too incase there isn't one on a particular button.
I am getting no response from the keydown function here, tried calling it on the div container aswell but still isn't firing.
import React from "react";
import ReactDOM from "react-dom";
export default function App() {
const keydown = () => {
console.log('pressed');
}
return (
<div id="container">
<button onKeyDown={keydown}>
test
</button>
</div>
);
}
Although it may differ for other libs components, for <button /> in React you can:
use onClick for mouse click event
use onKeyPress for keyboard event
Refer:
React document: keyboard-events
Assign an index: React not responding to key down event
import React from "react";
export default function App() {
const keydown = () => {
console.log("pressed");
};
const click = () => {
console.log("clicked");
};
return (
<div id="container">
<button onKeyPress={keydown}>Press</button>
<button onClick={click}>Click</button>
</div>
);
}
Try it online:
Extending from the #keikai answer, the convenient approach would be to focus the Button when the component loads. This can be done easily using a combination of useRef and useEffect hooks.
import React from "react";
const {useRef, useEffect } = React;
export default function App() {
const keydown = () => {
console.log("pressed");
};
const inputRef = useRef(null)
useEffect(() => {
inputRef.current.focus()
}, [])
return (
<div id="container">
<button ref={inputRef} onKeyDown={keydown}>Press</button>
</div>
);
}
I am use bootstrap modal in reactjs project. Here is the link of package which i have installed in my project: https://www.npmjs.com/package/react-responsive-modal
When, I click on open the modal button then it is working, but when i click on close button then close button is not working. I am using the hooks in my project. Below, I have mentioned my code:
import React, { useState } from 'react'
import Modal from 'react-responsive-modal'
const Login = () => {
const [open, openModal] = useState(false)
const onOpenModal = () => {
openModal({open: true})
};
const onCloseModal = () => {
openModal({open: false})
};
return(
<div>
<h1>Login Form</h1>
<button onClick={onOpenModal}>Open modal</button>
<Modal open={open} onClose={onCloseModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
export default Login;
The issue is because, you are setting object in state,
openModal({open: true})
This will store object in state.
setState require's direct value which needs to be change, your setState must be this,
const onOpenModal = () => {
openModal(!open) //This will negate the previous state
};
const onCloseModal = () => {
openModal(!open) //This will negate the previous state
};
Demo
You can simplify your code and just use 1 change handle for your modal,
const Login = () => {
const [open, openModal] = useState(false)
const toggleModal = () => {
openModal(!open)
};
return(
<div>
<h1>Login Form</h1>
<button onClick={toggleModal}>Open modal</button>
<Modal open={open} onClose={toggleModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
Demo
Your naming of the model hook is misleading and you're using the setState part of the Hook wrong, probably mixing it up with the this.setState convention for non-Hook React code.
import React, { useState } from 'react'
import Modal from 'react-responsive-modal'
const Login = () => {
const [modalOpen, setModalOpen] = useState(false)
const onOpenModal = () => {
setModalOpen(true)
};
const onCloseModal = () => {
setModalOpen(false)
};
return(
<div>
<h1>Login Form</h1>
<button onClick={onOpenModal}>Open modal</button>
<Modal open={modalOpen} onClose={onCloseModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
export default Login;