最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to make the background image change every X seconds in React? - Stack Overflow

programmeradmin4浏览0评论

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 badges
Add a ment  | 

6 Answers 6

Reset to default 4

I 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

发布评论

评论列表(0)

  1. 暂无评论