Detect mouse click and change state in React - reactjs

I have a div which is displayed depending upon a variable- eg: showDiv. After i set showDiv= true, div will appear.
{showDiv && <div id="someid"> text</div>}
Have set a timeout to change variable value so that div will disappear after a time (7 seconds)
thisState.setState({showDiv:true});
setTimeout(function(){
thisState.setState({false});
}.bind(this),7000);
How can i add a code to detect any mouse click and change variable based on that ? Requirement is that, div should disappear either
1. after 7 seconds (already done)
2. based on a click event (if user just clicks on the screen)
Any thoughts ?

You are looking for a window event-listener essentially.
componentDidMount(){
window.addEventListener("click", this.hideDiv)
}
hideDiv = () => {
if(this.state.showDiv){
this.setState({
showDiv: false
})
}
}
Also remember to remove that listener before the component unmounts:
componentWillUnmount{
window.removeEventListener("click", this.hideDiv)
}
See working sandbox: https://codesandbox.io/s/stupefied-silence-snhnw

Related

Framer / React: Can't change focus state of Text Input onClick / onChangePage

This is a Framer/React question:
I have a bunch of text fields in a "page" component and I want the focus to shift on every "page" change.
There's a button controlling the pager but no trigger (onPageChange / onClick) is changing the attribute of "focus" on the relevant text input.
This is the code I tried using to change the value of foc2 (the focus attribute) to true
When I manually change it to true it works, but in this case it doesn't
export function Page(): Override {
return {
currentPage: state.page,
onChangePage: (index) => {
state.page = index
state.foc2 = true
},
}
}
Do you have more complete code you could share?
Make sure you set the state to the index of the current focused input, and use that to change the currentPage property.
Happy to help if you send more context, you can also find more help in Framer's community at https://framer.com/r/discord

Slide page up to make room for iOS keyboard

In React (not React Native), how can I slide the page-content up to make room for the iOS keyboard when a textarea element gains focus?
Below please find my attempt. This now works fine. However, I am curious if this is considered good practice, or if there is an existing solution?
// When the textarea element gains focus,
// scroll the content up (to make room for the iOS keyboard)
scrollContent = () => {
console.log("Gained focus");
this.scrollViewRef.current.style.marginTop = '-250px';
}
// When the textarea element loses focus,
// scroll the content back down (since the iOS keyboard is gone now)
unScrollContent = () => {
console.log("Lost focus");
this.scrollViewRef.current.style.marginTop = '0px';
// The textarea's onBlur is causing the button's onClick not to fire
// so need to manually call the button's onClick
if(e.relatedTarget === this.buttonRef.current) {
this.buttonRef.current.click();
}
}
render() {
return (
<div
ref={this.scrollViewRef}
>
<textarea
onFocus={this.scrollContent}
onBlur={this.unScrollContent}
/>
<div
ref={this.buttonRef}
onClick={this.handleSubmitForm}
tabIndex="1"
>
Save
</div>
</div>
)
}
In particular, if the user tries to click on the form's submit button while the textarea element has the focus, it will only trigger the textarea's onBlur (and scroll the page-content up again), but it won't call the submit button's onClick. Hence the need to check what element was clicked on in the if statement, and if it was the button, manually trigger the click.
Is there a better way?

reactstrap alert automatic hidden

I am new in React and I use Alert - Dismissing from Reactstrap , I need the alert to automatically disappear after 2s. I tried to find some function that could be done, but unfortunately I did not. Thank you for help
Please have a look at this code,
hiding alert after a specific time
when you want to show the alert on some action, you can enable a state associated with that alert and disable it when you want to hide it.
I had a similar problem. My purpose was to show an Alert message after a Modal closed. I am using react-bootstrap for Modal and Alert component with useState and use Effects hooks.
const [visibleAlert, setVisibleAlert] = useState(false); --> init state
const handleVisible = () => { ---> Last State for Alert
setAlertVisible(true)
setTimeout(() => { ---> 2 seconds later which is closing
setAlertVisible(false)
}, 2000);
}
useEffect(() => {
handleClose(); ----> This is for Modal
return () => {
handleVisible(); ---> This is for Alert message
};
And this is my Alert component.
<Alert show={visibleAlert} variant="success"} dismissible>
Employee List Updated Successfully.
</Alert>
Alerts are something I like to play with: here is a full dynamic example where I set 1 alert and control it based on my requirements.
1st we need to set the alert. If you are using reactstrap use capital A for alerts
<Alert color={this.state.alertColor} isOpen={this.state.Alertvisible} toggle={(e) => this.setState({Alertvisible: false})}> {this.state.message} </Alert>
as you can see I can dynamically control the color, the visibility and the content of the alert without having to set multiple alerts.
here is the part where I control the alert
this.setState({
Alertvisible: true,
alertColor: 'success',
message: 'Alerts are awesome!'},
()=> {window.setTimeout(()=>{this.setState({Alertvisible:false})},8000)
});
So let me explain what is going on here!
with alertvisible: true we show the alert,
with alertcolor: we set the color according to the reactstrap or bootstrap
message: here we put the content of what we want to display
at the end you notice the window.setTimeout(()=> this is set to timeout in 8000 (8 seconds)
don't forget to add your states in the constructor.
I hope this helps :D

Can we trigger KeyPress on Div Tag in react

I have component where it displays questions . Each question is react component. On press of Enter it should navigate to next question. I have wired onKeyPress to Div element , but event gets captured sometimes , and sometimes it doesn't.
<div className="-" onKeyPress={(e) => this.navigateToNext(e)}>
<div className="preview-head">
//Other stuff here
</div>{/* preview-container*/}
</div>
navigateToNext(e) {
if (option.get('selected') === true && e.charCode === 13) {
this.goToNextQuestion();
}
}
Can anyone tell me any other way to handle this problem.
I would wire up an event listener in componentWillMount for the keyup event and check it's the enter key. Just remember to remove the event listener in componentWillUnmount.
I would guess the issue is around the div having focus or not. If it is not focused the key press event doesn't fire on that element and thus nothing happens
As said by #spirift, your div has not the focus. Try this :
Add ref={(c) => { this.ref = c }} to your div and focus in a lifecycle method :
componentDidMount() {
this.ref.focus();
}

How to wait and fade an element out?

I have an alert box to confirm that the user has successfully subscribed:
<div className="alert alert-success">
<strong>Success!</strong> Thank you for subscribing!
</div>
When a user sends an email, I'm changing the "subscribed" state to true.
What I want is to:
Show the alert box when the subscribed state is true
Wait for 2 seconds
Make it fade out
How can I do this?
May 2021 update: as tolga and Alexey Nikonov correctly noted in their answers, it’s possible to give away control over how long the alert is being shown (in the original question, 2 seconds) to the transition-delay property and a smart component state management based on the transitionend DOM event. Also, hooks are these days recommended to handle component’s internal state, not setState. So I updated my answer a bit:
function App(props) {
const [isShowingAlert, setShowingAlert] = React.useState(false);
return (
<div>
<div
className={`alert alert-success ${isShowingAlert ? 'alert-shown' : 'alert-hidden'}`}
onTransitionEnd={() => setShowingAlert(false)}
>
<strong>Success!</strong> Thank you for subscribing!
</div>
<button onClick={() => setShowingAlert(true)}>
Show alert
</button>
(and other children)
</div>
);
}
The delay is then specified in the alert-hidden class in CSS:
.alert-hidden {
opacity: 0;
transition: all 250ms linear 2s; // <- the last value defines transition-delay
}
The actual change of isShowingAlert is, in fact, near-instant: from false to true, then immediately from true to false. But because the transition to opacity: 0 is delayed by 2 seconds, the user sees the message for this duration.
Feel free to play around with Codepen with this example.
Since React renders data into DOM, you need to keep a variable that first has one value, and then another, so that the message is first shown and then hidden. You could remove the DOM element directly with jQuery's fadeOut, but manipulating DOM can cause problems.
So, the idea is, you have a certain property that can have one of two values. The closest implementation is a boolean. Since a message box is always in DOM, it's a child of some element. In React, an element is result of rendering a component, and so when you render a component, it can have as many children as you want. So you could add a message box to it.
Next, this component has to have a certain property that you can easily change and be completely sure that, as soon as you change it, the component gets re-rendered with new data. It's component state!
class App extends React.Component {
constructor() {
super();
this.state = {
showingAlert: false
};
}
handleClickShowAlert() {
this.setState({
showingAlert: true
});
setTimeout(() => {
this.setState({
showingAlert: false
});
}, 2000);
}
render() {
return (
<div>
<div className={`alert alert-success ${this.state.showingAlert ? 'alert-shown' : 'alert-hidden'}`}>
<strong>Success!</strong> Thank you for subscribing!
</div>
<button onClick={this.handleClickShowAlert.bind(this)}>
Show alert
</button>
(and other children)
</div>
);
}
}
Here, you can see that, for message box, either alert-shown or alert-hidden classname is set, depending on the value (truthiness) of showingAlert property of component state. You can then use transition CSS property to make hiding/showing appearance smooth.
So, instead of waiting for the user to click button to show the message box, you need to update component state on a certain event, obviously.
That should be good to start with. Next, try to play around with CSS transitions, display and height CSS properties of the message box, to see how it behaves and if the smooth transition happening in these cases.
Good luck!
PS. See a Codepen for that.
The correct way is to use Transition handler for Fade-in/out
In ReactJS there is synthetic event to wait till fade-out is finished: onTransitionEnd.
NOTE there are different css effects associated with different handlers. Fade is a Transition not an Animation effect.
Here is my example:
const Backdrop = () => {
const {isDropped, hideIt} = useContext(BackdropContext);
const [isShown, setState] = useState(true);
const removeItFromDOM = () => {
debugger
setState(false)
};
return isShown
? <div className={`modal-backdrop ${isDropped ? 'show' : ''} fade` } onClick={hideIt} onTransitionEnd={removeItFromDOM}/>
: null
}
An other way is to solve this with a CSS3 transition.
https://www.tutorialspoint.com/css/css_animation_fade_out.htm
You can add a new class to the alert (like .hidden) and then you can relate .hidden with the class you defined for the alert.
alert.hidden{
// Here you can define a css transition
}
In this solution you don't have to add a setInterval or anything, since css3 transitions already process it on browser render.

Resources