jsdev
jsdev

Reputation: 33

How do you generate random items from an array without repeating in React.js?

Below is a snippet of my code.. I'm working on a random quote generator and would like to find a solution on generating each random quote and background from the arrays without repeats until all have been used, and then cycling through again. The background images are being imported directly into the state and the quote array is imported from a separate file. I've attempted slicing each item from the array and pushing it into an empty one, but so far that has been unsuccessful.

   constructor(props) {
        super(props);
        
        this.state = {
            quote: quotes[0].quote,
            author: quotes[0].author,
            backgrounds: [
                photos..
            ]
        };
    }
    
    
    shuffleAll = (arr) => {
        return arr.sort(function () { return 0.5 - Math.random() });
    }
    
    findRandomQuote = (arr) => {
        let num = Math.floor(Math.random() * quotes.length);
        let randQuote = quotes[num];
        this.shuffleAll(quotes);
        this.setState({
            quote: randQuote.quote,
            author: randQuote.author
        });
    }

    findRandomBackground = (arr) => {
        const { backgrounds } = this.state;
        let background = backgrounds[Math.floor(Math.random() * backgrounds.length)];
        this.shuffleAll(backgrounds);
        document.body.style.background = `url(${background})`;
    }

Upvotes: 0

Views: 563

Answers (1)

Steven Hardy
Steven Hardy

Reputation: 111

You can use state to store the quote array, and substract from it until all quotes are used up:

constructor(props) {
    super(props);
    this.state = {
        availableQuotes: [...quotes],
        activeQuote: null
    };
}

findRandomQuote = () => {
    const quoteOptions = this.state.availableQuotes.length > 0 ? this.state.availableQuotes : quotes;
    const randomIndex = Math.floor(Math.random() * quoteOptions.length);
    this.setState({
        availableQuotes: [...quoteOptions].splice(randomIndex, 1),
        activeQuote: quoteOptions[randomIndex]
    });
}


// This runs after component mounts, to set the first random quote
componentDidMount() { 
    this.findRandomQuote();
}

You can do a similar thing to randomise the background images.

Upvotes: 1

Related Questions