FINAL EDIT:
See working code below:
import React, { Component } from 'react';
var images = [
".ashx",
".jpg"
]
class App extends Component {
constructor(props) {
super(props);
this.state = { imgPath: "url(" + images[1] + ")" };
}
ponentDidMount() {
this.interval = setInterval(() => {
this.setState({ imgPath: "url(" + images[0] + ")" })
}, 1000);
}
ponentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div className="App">
<div className='dynamicImage' style={{ backgroundImage: this.state.imgPath }} >
{console.log(this.state.imgPath)}
</div>
</div >
);
}
}
FINAL EDIT:
See working code below:
import React, { Component } from 'react';
var images = [
"https://www.royalcanin./~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx",
"https://upload.wikimedia/wikipedia/mons/4/4d/Cat_March_2010-1.jpg"
]
class App extends Component {
constructor(props) {
super(props);
this.state = { imgPath: "url(" + images[1] + ")" };
}
ponentDidMount() {
this.interval = setInterval(() => {
this.setState({ imgPath: "url(" + images[0] + ")" })
}, 1000);
}
ponentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div className="App">
<div className='dynamicImage' style={{ backgroundImage: this.state.imgPath }} >
{console.log(this.state.imgPath)}
</div>
</div >
);
}
}
ORIGINAL THREAD:
I'm trying to use setInterval() to change the image dynamically every X seconds.
I just don't understand where setInterval is supposed to be placed within the code, or what its output is supposed to be.
My current code is:
import React, { Component } from 'react';
// Paths to my images
var images = [
"https://www.royalcanin./~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx",
"https://upload.wikimedia/wikipedia/mons/4/4d/Cat_March_2010-1.jpg"
]
var imgPath = "url(" + images[1] + ")" // Set original value of path
function f1() {
imgPath = "url(" + images[0] + ")" // Change path when called ?
}
class App extends Component {
render() {
setInterval(f1, 500); // Run f1 every 500ms ?
return (
<div className="App">
<div className='dynamicImage' style={{ backgroundImage: imgPath }} > // Change background image to one specified by imgPath
</div>
</div >
);
}
}
export default App;
The current code outputs the first imgPath's URL, but fails to update it to the one specified within the function f1. To the best of my knowledge, the function f1 does appear to run, as removing it, or setting an undefined variable does return an error. I just can't get it to change imgPath.
Any ideas on what I'm doing wrong, or how I could improve my code?
Cheers
Edit: Commented code + removed unnecessary lines
Share Improve this question edited Mar 2, 2019 at 12:49 poultrynews asked Mar 2, 2019 at 12:17 poultrynewspoultrynews 6492 gold badges9 silver badges16 bronze badges6 Answers
Reset to default 4I would move all your variables into your ponent and as Akash Salunkhe suggests, use ponnentDidMount to setInterval. Don't forget to clear the interval when the ponent unmounts.
This answer will also work with using any number of images.
class App extends React.Component {
constructor(props) {
super(props);
const images = [
"https://www.royalcanin./~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx",
"https://www.petfinder./wp-content/uploads/2013/09/cat-black-superstitious-fcs-cat-myths-162286659.jpg",
"https://upload.wikimedia/wikipedia/mons/4/4d/Cat_March_2010-1.jpg"
];
this.state = {
images,
currentImg: 0
}
}
ponentDidMount() {
this.interval = setInterval(() => this.changeBackgroundImage(), 1000);
}
ponentWillUnmount() {
if (this.interval) {
clearInterval(this.interval);
}
}
changeBackgroundImage() {
let newCurrentImg = 0;
const {images, currentImg} = this.state;
const noOfImages = images.length;
if (currentImg !== noOfImages - 1) {
newCurrentImg = currentImg + 1;
}
this.setState({currentImg: newCurrentImg});
}
render() {
const {images, currentImg} = this.state;
const urlString = `url('${images[currentImg]}')`;
return (
<div className="App">
<div className='dynamicImage' style={{backgroundImage: urlString}} >
</div>
</div >
);
}
}
You might want to use this.props
or this.state
to store the imgPath
, otherwise React doesn't know you have changed anything.
Put image path in state and in ponentDidMount, use setInterval and inside it use setState to change image path.
@Anurag is correct. You need to use setInterval
in ponentDidMount
and ensure that you call this.setState
if you want the render method to rerender. This of course requires that you store the image path in this.state
You can create an endless loop similar to this, you might want to use an array of image urls and write some logic for that. But as you can see I have an endless loop created for the function setImage()
:
constructor(props) {
super();
this.state = {
image1: props.imageUrls[0],
image2: props.imageUrls[1],
changeImage: true
};
this.setImage();
}
setImage() {
setTimeout(() => {
this.setState({ changeImage: !this.state.changeImage }, this.setImage());
}, 3000);
}
You need to use ponentDidMount() React Lifecycle method to register your setInterval function.
Here is a working example
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
images: [
"https://picsum.photos/200/300/?image=523",
"https://picsum.photos/200/300/?image=524"
],
selectedImage: "https://picsum.photos/200/300/?image=523"
};
}
ponentDidMount() {
let intervalId = setInterval(() => {
this.setState(prevState => {
if (prevState.selectedImage === this.state.images[0]) {
return {
selectedImage: this.state.images[1]
};
} else {
return {
selectedImage: this.state.images[0]
};
}
});
}, 1000);
this.setState({
intervalId
});
}
ponentWillUnmount() {
clearInterval(this.state.intervalId);
}
render() {
return (
<div className="App">
<img src={this.state.selectedImage} alt={"images"} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
You can change around the code and can find live demo here: https://codesandbox.io/s/0m12qmvprp