How to change interval value in React - reactjs

I've tried changing the interval value when using ReactJs, but can't seem to get it to work. I've looked it up but haven't found anything useful (or maybe I didn't get to it while reading). I have most of my code inside a class component.
My code looks like this:
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = {
tickS: 1000,
...
};
}
componentDidMount() {
this.intervalID = setInterval(
() => this.tick(),
this.state.tickS
);
}
tick(){
this.setState({
...
tickS: 10**Math.log10(this.state.tickS + this.state.clicksChange),
...
});
}
}
It does work for using 1000 milliseconds, but when i try to redefine the state of tickS, it doesn't work.

You can't change the interval of setInterval. Instead, you can take another approach and use setTimeout for the same purpose. Check out the example:
class Timer extends React.Component {
constructor(props) {
super(props);
this.ticks = 1000;
}
componentDidMount() {
this.timeoutID = setTimeout(
() => this.tick(),
this.tick
);
}
tick() {
this.setState({
...
});
this.ticks = 10 ** Math.log10(this.ticks + this.state.clicksChange),
this.timeoutID = setTimeout(
() => this.tick(),
this.ticks
);
}
}

Related

How can I define a method inside a class component in React?

I have made a simple digital clock in React. It seems working. However, I wanted to define the callback function inside the setState() separately. But I got an error. Do you know how I can define such a function called tick() outside the componenDidMount? Below is my code
import "./Clock.css";
class Clock extends React.Component {
state = { date: new Date() };
componentDidMount() {
setInterval(() => {
this.setState({ date: new Date() });
}, 1000);
console.log("componentdidmount");
}
render() {
return (
<div className="clock-container">
<h1 className="clock">{this.state.date.toLocaleTimeString()}</h1>
</div>
);
}
}
export default Clock;
Is this what you want it to be like?
tick(){
this.interval = setInterval(() => {
this.setState({ date: new Date() });
}, 1000);
}
componentDidMount() {
this.tick();
console.log('componentdidmount');
}
componentWillUnmount(){
clearInterval(this.interval);
}

Rendering a new component inside componentDidMount - React

I will have to render a new component after all the expected components are loaded. I will need a timeout based on which the the new component has to be rendered. So this new component has to show up after 5 minutes after the page has loaded.
I need to render a component called new_component that extends React.component
public componentDidMount(): void {
if (visited) {
setTimeout(() => {
console.log('Reached the timeout')
//Render the new conponent here. (Not sure how to call the render function of another component here)
}, timeout);
}
Can someone help me call the render function of new_component inside componentDidMount please. i tried new_component.render(). But that does not seem to work.
You can use state to track this.
componentDidMount() {
setTimeout(() => {
this.setState({ showNewComponent: true })
})
}
and in render:
render() {
if (this.state.showNewComponent) {
return <NewComponent />
}
return null
}
You can go with this code, wait and then render new one:
cosnt FIVE_MIN = 5 * 60 * 1000
class Example {
this.state = { isShowComponent: false }
timer
componentDidMount() {
this.timer = setTimeout(() => {
this.setState({ isShowComponent: true })
}, FIVE_MIN)
}
componentWilllUnmount() {
clearTimeout(this.timer)
}
render() {
if (this.state.isShowComponent) return <NewComponent />
return <Component />
}
}
:)
you can render your component by your state.
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {
isTimeout: false,
};
}
componentDidUpdate(prevProps, prevState) {
this.checkTimeout = setTimeout(() => {
this.setState(() => ({isTimeout: true}))
}, 500);
}
componentWillUnmount() {
// clean it up when the component is unmounted.
clearTimeout(this.checkTimeout);
}
render () {
if (isTimeout) {
return (k<h1>time is running out</h1>)
}
return (<h1>hello world.</h1>)
}
}

Arrow function ambguity in ReactJS

class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
In the above code - I wasn't able to understand the setInterval() line - to be precise the function argument of the setInterval line. I think it is an arrow function- I might be wrong. I replaced it with a regular function setInterval(function(){this.tick()},1000) and got an error saying tick() is not a function. What's happening here?
The this reference is reset when using old-style function() syntax, whereas with => (arrow-functions) the this reference is preserved. You can still use function() but you need to call .bind(this) to "fix" the this reference.
So this:
this.timerID = setInterval(
() => this.tick(),
1000
);
Is equivalent to this:
this.timerID = setInterval(
function() { this.tick(); }.bind(this),
1000
);
You need to do this because setTimeout/setInterval is a member-property of the global (window) object, so inside a setTimeout or setInterval callback the this reference is for window, not the call-site's this.

how manage proper way to implement Countdown Timer for two players in react js?

I am a newbie for react js. how to manage two Countdown timers first start and second is stop after 5-second interval second start and first stop.
it work for single Clock successful but add two clocks then first only start and not stop while second not start I don't know how do this ?.
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
isActive: true
};
}
componentDidMount() {
this.intervalId = setInterval(() => {
this.randomCallObject();
}, 5000);
}
randomCallObject() {
this.setState({
Active: !this.state.isActive
});
}
render() {
let clock= {
time: 150,
isActive:this.state.isActive
}
let clock2= {
time: 100,
isActive:!this.state.isActive
}
return (
<div className="container">
<Clcok ClockData={clock}/>
<Clcok ClockData={clock2}/>
</div>
);
}
}
import React, { Component } from "react";
const TOTAL_MINUTES = 60;
export default class ClockComponent extends Component {
constructor(props) {
super(props);
this.state = {
time: props.ClockData.time,
isActive: props.ClockData.isActive
};
}
componentDidMount() {
const { isActive } = this.state;
if (isActive === true) {
this.intervalId = setInterval(() => {
const { time } = this.state;
if (time > 0) {
this.setState({
time: time - 1
});
}
}, 1000);
}
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
render() {
const { time } = this.state;
let minutes ="" + Math.floor((time % (TOTAL_MINUTES * TOTAL_MINUTES))/ TOTAL_MINUTES);
let seconds = "" + Math.floor(time % TOTAL_MINUTES);
if (isNaN(minutes) || isNaN(seconds)) {
return null;
}
if (minutes.length === 1) {
minutes = `0${minutes}`;
}
if (seconds.length === 1) {
seconds = `0${seconds}`;
}
return (
<div className="row">
<div className="col-md-1">
<div>
{minutes}:{seconds}
</div>
</div>
</div>
);
}
}
when clock data comes from props so take simple objects when isActive flag is true then clock timer on when isActive false then timer stop
To learn how to handle setInterval with React, I suggest you read the following blog post by Dan Abramov:
Making setInterval Declarative with React Hooks
In it, he explains how to use setInterval using React Hooks and also how to do it using a class component. On the post, there is also a link to a CodeSandbox example where you can see it in action.
What I did was create another CodeSandbox where you can see how you could apply this example to run multiple timers:
https://codesandbox.io/embed/timers-l6me1
I've used React Hooks in the example because they don't require a lot of code.
I hope it helps.
edit #1
Here is an example of a Counter component taken directly from the mentioned article, and adapted to fit the latter example.
class Counter extends React.Component {
state = {
count: 0,
delay: 1000,
isRunning: true
};
constructor(props) {
super(props);
this.state = { ...this.state, ...props };
}
componentDidMount() {
this.interval = setInterval(this.tick, this.state.delay);
}
componentDidUpdate(prevProps, prevState) {
if (prevState.delay !== this.state.delay) {
this.startInterval();
}
}
componentWillUnmount() {
clearInterval(this.interval);
}
startInterval = () => {
clearInterval(this.interval);
this.interval = setInterval(this.tick, this.state.delay);
console.log(this.interval);
};
tick = () => {
this.setState({
count: this.state.count + 1
});
};
handleDelayChange = e => {
this.setState({ delay: Number(e.target.value) });
};
toggleCounter = () => {
console.log(this.state.isRunning);
if (this.state.isRunning) {
clearInterval(this.interval);
} else {
this.startInterval(this.state.delay);
}
this.setState({
count: 0,
isRunning: !this.state.isRunning
});
};
render() {
const {
state: { isRunning, delay, count },
toggleCounter,
handleDelayChange
} = this;
return (
<>
<h1>{count}</h1>
<input value={delay} onChange={handleDelayChange} />
<button onClick={toggleCounter}>{isRunning ? "stop" : "start"}</button>
</>
);
}
}

React js Delay rendering causes error

I have form where I should render one of elements in a while. I use setTimeout for this aim in componentDidMount but I get warning setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
class Form extends React.Component {
constructor(props, context) {
this.state = {resend: false};
}
componentDidMount() {
const max = 3;
if (this.props.count < max) {
setTimeout(() => {
this.setState({resend: true});
}, 1000);
}
}
render() {
return (
<form>
...
{this.state.resend ? <Component/> : null}
</form>
);
}
}
Your component is probably unmounting at some point, then the timeout finishes, and it attempts to call setState after your component is no longer being rendered.
You need to cancel any timeouts you have running in componentWillUnmount. Store a reference to them and delete them.
class Form extends React.Component {
constructor(props, context) {
this.state = {resend: false};
this.timeouts = [];
}
componentWillUnmount(props, context) {
this.timeouts.forEach(t => window.clearTimeout(t));
}
componentDidMount() {
const max = 3;
if (this.props.count < max) {
const timeoutId = setTimeout(() => {
this.setState({resend: true});
}, 1000);
this.timeouts.push(timeoutId);
}
}
render() {
return (
<form>
...
{this.state.resend ? <Component/> : null}
</form>
);
}
}
This might be because the component doesn't exist when the setTimeout calls. Use a mounted flag to see if the component still exists.
constructor(props, context) {
this.state = {resend: false};
this.mounted = true;
}
componentWillUnmount() {
this.mounted = false;
}
componentDidMount() {
const max = 3;
if (this.props.count < max) {
setTimeout(() => {
if (!this.mounted) return;
this.setState({resend: true});
}, 1000);
}
}

Resources