Probelm with timer React UseEffect - javascript

i have this code that works almost 100%.
function App() {
const [breakLength, setBreakLength] = React.useState(300)
const [sessionLength, setSessionLength] = React.useState(1500)
const [whichTimer, setWhichTimer] = React.useState (true)
const [timerOn, setTimerOn] = React.useState (false)
const [time, setTime] = React.useState (sessionLength)
React.useEffect(()=>{
setTime (sessionLength)},[sessionLength])
React.useEffect(() => {
if(timerOn){
const timerId = setInterval(() => {
setTime((t)=>{
if (t<=0 && whichTimer){
setWhichTimer (!whichTimer)
return breakLength
}
else if (t<=0 && !whichTimer){
setWhichTimer (!whichTimer)
return sessionLength
}
else {
console.log(whichTimer)
return t-1
}
} )
},1000)
return () => clearInterval(timerId)
}
}, [timerOn])
return (
<div id="container">
<div id="break-label">Break Length</div>
<div id="session-label">Session Length</div>
<div id="break-length">{breakLength}</div>
<div id="session-length">{sessionLength}</div>
<div id="timer-label">{whichTimer? "Session" : "Break"}</div>
<div id="time-left">{time}</div>
<button id="start_stop" onClick={()=>setTimerOn(!timerOn)} >Start</button>
</div>
);
}
ReactDOM.render (<App />, document.getElementById ("root"))
The problem is in the second UseEffect.
This is a timer that have a Session Length and a Break Length.
When Session reaches to 0, starts the break.
Until then i have no problem, but when break reaches to 0 it doesn´t change to Session, break start again.
I´ve put a console.log to see if "whichtimer" changes, and it doesn´t. I really don´t understand why.
Thanks for taking the time

Related

Function does not work when I go to the page back, and then return to the page (React)

function Final_Set(){
return(
<div id="exercise_sets_decider_box">
{
(function(){
console.log(1);
Final_set_page();
})()
}
</div>
);
function App(){
const [mode, Setmode] = useState("0");
if (mode === "0"){
$(document).on('click', "#purple_box_1", function(e){
Setmode("Final");
});
return(
<div id="purple_box_1">
</div>
);
} else if(mode==="Final"){
$(document).on('click', "#purple_box_2", function(e){
Setmode("0");
});
return(
<div>
<Final_Set></Final_Set>
<div id="practice"></div>
<div id="purple_box_2">
</div>
</div>
)
}
}
In brief, Final_set_page function is appending html code in div:#practice, like $("#practice").append('blahblah'). If I go from mode '0' to mode 'Final', Final_set_page() is well working. But if I return to mode '0' and go back to mode 'Final', console.log() is well working but Final_set_page() is not working. I don't know the reason, and I can't find the solution. Please help!
Maybe the problem is in jQuery.
I have rewritten the code. Maybe edit this code instead according to your needs.
By the way, we have no idea what Final_set_page is...
function Final_Set() {
useEffect(() => {
console.log(1);
Final_set_page(); // I don't know what it is, so leaving it here. Move it if it is a component.
}, []); // [] empty dependency array means useEffect only runs once.
return (
<div id="exercise_sets_decider_box">
exercise_sets_decider_box
</div>
);
}
function App() {
const [mode, setMode] = useState("0"); // SetMode does not follow the convention for naming variables.
const handlePurpleBox1Click = () => setMode("Final"); // I moved this to separate functions so it is easier for you to edit them further.
const handlePurpleBox2Click = () => setMode("0");
if (mode === "0") {
return (
<div id="purple_box_1" onClick={handlePurpleBox1Click}>
purple_box_1
</div>
);
}
if (mode === "Final") { // if the previous return worked, this code is not reachable. This looks cleaner to me.
return (
<div>
<Final_Set></Final_Set>
<div id="practice"></div>
<div id="purple_box_2" onClick={handlePurpleBox2Click}>
purple_box_2
</div>
</div>
)
}
return <></> // add this, so the component returns something just in case.
}

Difference between using the arrow function and normal function inside useEffect in the following code

I am new to React js and I am implementing the useEffect for the first time in my code. I followed few tutorials and they have done things differently as follows
Case l:
function App() {
const[counter,setCounter] = useState(0);
const[toggle,setToggle] = useState(false);
const incrementer = () =>{
// counter+=1
setCounter(counter + 1);
console.log(counter)
};
const toggler = () =>{
setToggle((toggle) => !toggle);
};
return (
<div className="App">
<h1 className = {toggle ? 'active' : ''} >Hello world!!</h1>
<h1>{counter}</h1>
<h1>{abc}</h1>
<button onClick={incrementer} >Click</button>
<button onClick={toggler}>Toggle Here</button>
<div className="home">
<h1>{Date.time}</h1>
<Nav/>
<Tweets/>
</div>
</div>
);
}
Here inside the incrementer function, I am just using counter+1 and it gives the required result and makes sense. It increases the count by 1 on every click.
Now case 2:
function App() {
const[counter,setCounter] = useState(0);
const[toggle,setToggle] = useState(false);
const incrementer = () =>{
setCounter(() => counter+1);
console.log(counter)
};
const toggler = () =>{
setToggle((toggle) => !toggle);
};
return (
<div className="App">
<h1 className = {toggle ? 'active' : ''} >Hello world!!</h1>
<h1>{counter}</h1>
<h1>{abc}</h1>
<button onClick={incrementer} >Click</button>
<button onClick={toggler}>Toggle Here</button>
<div className="home">
<h1>{Date.time}</h1>
<Nav/>
<Tweets/>
</div>
</div>
);
}
In this case, inside the incrementer function, it is using what seems like an arrow function. I assume it is using function inside the function. Also, it is not passing anything as () is empty. How the count is increasing here. I am confused.
Also inside the toggler function, I can write abc or any variable instead of toggle and it works. How??
Update
Ok my main confusion is in this code.
const incrementer = () =>{
// counter+=1
setCounter((kkk) => kkk + 1);
// setCounter(() => counter+1);
console.log(counter)
};
This function works as well. How is this kkk value is getting the value of counter=0. Shouldnt we be writing counter instead of kkk??
Not only react hooks could use arrow functions in this way, but almost all cases in Javascript. Maybe we could have explanation in Comparing traditional functions to arrow functions

React useState performing very badly

I am having trouble understanding the problem in this code:
export default function CustomPopup({wi,he,children}) {
//some code
const [popupSize,setPopupSize] = useState([`${wi}px`,`${he}px`])
const handlePopupSize = () =>{
let c = [];
(window.innerWidth < (wi/0.9)) ? c[0] = `90%` : c[0] = `${wi}px`;
(window.innerHeight < (he/0.8)) ? c[1] = `80%` : c[1] = `${he}px`;
if (c != popupSize) { setPopupSize(c) };
}
window.addEventListener("resize", handlePopupSize)
return (
<div className="popup--page--wrapper">
<div className="popup--box" style={{width: popupSize[0], height: popupSize[1]}}>
{ children }
</div>
</div>
)
}
When I resize the page, the page lags massively and even make the browser bug.
There seems to be something wrong with the code, but I can't find out.
Thanks in advance!
You need to add the event listener in a useEffect hook.
import React, { useState, useEffect } from 'react'
.....
.....
useEffect(() => {
window.addEventListener("resize", handlePopupSize)
return () => window.removeEventListener("resize", handlePopupSize)
},[])
Your current code creates a loop of addEventListeners, because a listener is created on every single render, and setting state is causing a new render on every resize.

How to use useEffect() correctly?

I want to change style by scrolling.
This code isn't working correctly
.
When I rolling up and down too many times and too fast, then the browser is going to freeze, crash.
I think I used useEffect() wrong. How can I solve this issue.
const ArticleItem = ({title, content, active, chapter, program, id, scrollPos}) => {
const ref = useRef(null);
const client = useApolloClient();
useEffect(() => {
if(ref.current.offsetTop <= (scrollPos + 200)) {
client.writeData({data: {
curChapter: chapter.num,
curArticle: id,
curProgram: program.name
}});
}
});
if(active === false)
return ( // Inactive Article
<div className='section-item' ref={ref}>
<h2>{title.toUpperCase()}</h2>
<ReactMarkdown source={content} />
<br />
</div>
)
return ( // Active Article
<div className='section-item active' ref={ref}>
<h2>{title.toUpperCase()}</h2>
<ReactMarkdown source={content} />
<br />
</div>
)
}
As a Result, I faced this warning.
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
I think this is the reason of issue?!
Based on my comment above, you need to include the dependency array for useEffect also. In the current way it is running infinitely. Probably you want to include scrollPos into that thus it would only triggered once scrollPos is changing.
Try the following:
useEffect(() => {
if(ref.current.offsetTop <= (scrollPos + 200)) {
client.writeData({data: {
curChapter: chapter.num,
curArticle: id,
curProgram: program.name
}});
}
}, [scrollPos]);
I hope this helps!
Well, the problem is triggered all the time you can use the scroll event listener and make your changes when this event is triggered.
const [scrollItem, setScrollItem] = useState(null);
const handleScroll() {
if(scrollItem) {
// logic goes here
}
}
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []); // initialize event only once
return (
<div ref={setScrollItem}>
...
</div>
);
EDIT
Avoid that solution, #norbitrial is right

React Js AwesmeSlider Autoplay

Hey im a bit new to React. I found this slider which I have implemented and it works fine.
https://caferati.me/demo/react-awesome-slider
My only issue now is I would like it to Autoplay but it seems I cant wrap my head around it. As I understand I need to make a function which will do it for me?
My code so far is.
class Slider extends Component {
render() {
return (
<div className="slider">
<AwesomeSlider cssModule={styles} onFirstMount={slider}>
<div data-src={image2}>
<div className="sliderText">
<div>
<h1>Text For first sike</h1>
<NewsletterButton className="clickMe" text={I18n.t('ClickMe')}/>
</div>
</div>
</div>
<div data-src={image4}>
<Fade left duration={2300}>
<img className="sliderImage2" src={image3}/>
</Fade>
<Zoom duration={2000}>
<div className="sliderText2">
<h1> Text For Slide2 </h1>
<p>Slide 2 Paragraph</p>
</div>
</Zoom>
</div>
<div data-src={image4}>
<Zoom duration={2000}>
<div className="sliderText3">
<h1> Slide3 </h1>
<p>Slider 3 paragrah</p>
</div>
</Zoom>
<Fade bottom duration={2300}>
<img className="sliderImage3" src={image1}/>
</Fade>
</div>
</AwesomeSlider>
</div>
);
}
}
export default Slider;
You can give the below approach a try:
Create a timer (as you are looking for an autoplay) which runs for every 2 seconds or so and call a method named setNextImage in it.
In your componentDidUpdate(),
setTimeout(this.setNextImage, 2000);
In your method write some logic to update state.
setNextImage: function() {
// setState method is used to update the state
let index = this.state.currentIndex;
if(index == yourMax_Image_Count)
index == 1
this.setState({ : this.state.currentIndex -1 });
},
I see there is a attribute selected in AwesomeSlider and you can set this.state.currentIndex as its value
Make sure you are handling timeout properly.
You can get next button with jQuery and use click() function like this
$(document).ready(function () {
setInterval(function() {
$(".button_class").click();
}, 10000);
});
componentDidMount() {
const interval = setInterval(this.handleNextSlide, 12500);
this.interval = interval; }
componentWillUnmount() {
if (this.interval != null) {
clearInterval(this.interval);
} }
handleNextSlide = () => {
const { dataSource } = this.props;
const { currentIndex } = this.state;
if(currentIndex == (dataSource && dataSource.length) - 1) {
this.setState({
currentIndex: 0
});
} else {
this.setState({
currentIndex: this.state.currentIndex + 1
});
} }
render() {
const { dataSource } = this.props;
const { currentIndex } = this.state;
return (
<AwesomeSlider
selected={currentIndex}
cssModule={AwsSliderStyles}
>
{dataSource && dataSource.map((value, key) => {
return (
//Do some stuff.
);
})}
</AwesomeSlider>
);
}
try this by importing "withautoplay"
import withAutoplay from 'react-awesome-slider/dist/autoplay'
const AutoplaySlider = withAutoplay(AwesomeSlider)
and use autoplay tag in your component
<AutoplaySlider
play
cancelOnInteraction={false} // should stop playing on user interaction
interval={6000}
>
<div data-src=/path/to/image.png />
<div data-src=/path/to/image.png />
<div data-src=/path/to/image.png />
</AutoplaySlider>
you can follow this link for more details https://www.npmjs.com/package/react-awesome-slider

Categories

Resources