Search code examples
javascriptreactjspokeapi

Display an image from an api for 24 hours


I'm doing a project in React, and on my "Home.js" page I would like to display a pokemon randomly for 24 hours thanks to the PokeApi (https://pokeapi.co/). But I can't add the fact that the Pokemon image should be displayed for 24 hours.

For now I have already tried this, it displays an image but it changes when you refresh the page.

Here is my line of code so far:

Home.js :

<div className="rightPane">
        {dataPkmn && dataSpecies ? <PokemonDuJour id={Math.floor(Math.random() * (898 - 1)) + 1} /> : <div></div>}
        </div>

Can you help me please to know what should I add in my code? thank you in advance for your help

PokemonDuJour.js

const PokemonDuJour = (props) => {

    const param = useParams()

    const [pkmnId, setPkmnId] = useState();
    const [img, setImg] = useState(String);
    const [name, setName] = useState(String);
    const [type1, setType1] = useState("");
    const [type2, setType2] = useState("");
    const [data, setData] = useState();
    const [species, setSpecies] = useState();

    //REDUX
    const dataPkmn = useSelector((state) => state.dataPkmn.pkmn)
    const dataSpecies = useSelector((state) => state.dataPkmn.species)

    const navigate = useNavigate();

    const handleClick = () => {
        if (pkmnId) {
            setType1("")
            setType2("")
            navigate("/pokemon/" + pkmnId);

        }
    }

    useEffect(() => {
        if (data && species) {
            if (data.sprites.other.dream_world.front_default != null) {
                setImg(data.sprites.other.dream_world.front_default)
            } else if (data.sprites.other.home.front_default != null) {
                setImg(data.sprites.other.home.front_default)
            }
            setType1(data.types[0].type.name)
            if (data.types.length > 1) {
                setType2(data.types[1].type.name)
            }
            setPkmnId(data.id)

            species.names.forEach(element => {
                if (element.language.name == "fr") {
                    setName(element.name)
                }
            });
        }
    }, [data && species]);
    useEffect(() => {
        if (dataPkmn) {
            setData(dataPkmn.payload[props.id - 1])
        }
    }, [dataPkmn && param])

    useEffect(() => {
        if (dataSpecies) {
            setSpecies(dataSpecies.payload[props.id - 1])
        }
    }, [dataSpecies && param]);

    return (
        <div className='card' >
            {
                data ?
                    <div className="pkmnDuJour" onClick={handleClick}>
                        <p className='pkmnName'>{name}</p>
                        <img src={img} alt="pkmnImage" className='pkmnImage' />
                        
                    </div>
                    :
                    <div></div>
            }

        </div>
    );
};

export default PokemonDuJour;


Solution

  • Following up on my comment: You need to generate a deterministic ID based on the current date, but it needs to be one that seems "random". This problem could be solved a number of ways, but here's one:

    1. Generate shuffled array of pokemon IDs and include the array as a constant in your source code. The following snippet demonstrates how you could do that. Copy the array value and paste it into your JavaScript module source code, saving it with a variable name (e.g. pokemonIds). You will refer to this shuffled array in the next part.

    /**
     * Durstenfeld shuffle
     *
     * - https://stackoverflow.com/a/12646864/438273
     * - https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
     */
    function shuffleArray (array) {
      for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
    }
    
    /** Get shuffled array of all pokemon ID values */
    function generateShuffledIntegerArray (minId = 1, maxId = 898) {
      const arr = [];
      for (let i = minId; i <= maxId; i += 1) arr.push(i);
      shuffleArray(arr);
      return arr;
    }
    
    const arrayString = `[${generateShuffledIntegerArray().join()}]`;
    console.log(arrayString);

    1. Create a function to get the current UNIX time, rounded to the nearest 24 hours (so the value only changes once per day). Get the remainder (%) of dividing this value by the length of the array and use it as the index of the pokemon ID in your shuffled array:

    // Generated using the code snippet above
    const pokemonIds = [162,606,843,194,531,39,838,805,724,251,389,607,510,216,60,582,407,501,633,787,594,643,569,654,898,352,131,62,611,296,536,209,223,747,857,850,622,468,530,615,563,855,733,831,25,825,47,49,791,758,889,703,823,134,708,885,390,41,335,782,232,23,711,219,112,494,839,301,137,298,449,380,507,752,329,382,413,650,276,846,120,114,421,726,43,844,757,590,532,29,269,357,580,612,206,544,671,398,445,300,203,877,763,619,124,211,684,262,801,321,789,682,235,858,107,481,437,244,369,362,133,756,283,515,422,736,602,217,322,388,240,285,381,521,534,65,852,5,154,226,803,879,784,99,585,70,834,161,54,813,778,833,238,141,538,878,490,578,175,201,666,753,564,340,184,553,699,28,632,26,652,663,159,312,727,370,355,754,687,106,555,780,20,762,404,722,659,816,197,234,372,125,854,147,158,830,4,812,80,500,662,136,228,279,886,432,700,373,185,819,341,503,31,718,755,571,874,749,19,851,97,866,497,828,69,315,853,444,239,396,759,333,795,868,512,760,42,263,331,212,170,204,483,799,796,48,627,550,172,243,319,339,664,363,377,892,145,132,344,230,284,596,587,470,246,53,526,751,802,386,384,548,584,186,875,655,770,567,143,516,156,392,405,408,277,744,463,96,642,807,220,668,21,731,785,295,395,489,638,440,214,476,741,109,842,361,88,236,527,566,371,702,560,151,628,306,139,737,359,613,410,416,222,271,393,609,104,412,809,518,788,215,100,64,871,127,163,168,356,691,576,677,208,672,83,589,641,509,504,426,304,248,10,310,237,617,196,523,255,734,451,14,385,366,221,506,768,130,270,378,292,869,568,498,767,78,701,375,231,661,565,425,583,690,790,367,191,495,146,631,595,640,742,334,732,837,797,287,535,126,697,719,174,520,150,525,79,660,896,717,265,715,311,713,696,402,658,774,278,513,880,273,895,561,349,639,674,195,884,452,679,188,102,709,116,9,8,115,695,456,85,436,111,336,63,427,233,129,496,157,250,179,505,511,461,293,180,556,327,781,465,66,862,685,294,258,6,33,282,218,91,18,457,182,267,61,673,95,118,178,169,32,841,818,771,716,829,346,330,469,207,519,433,488,680,675,665,318,17,804,397,324,419,459,579,289,810,345,669,314,144,365,776,840,723,455,623,524,453,775,546,434,247,558,689,450,332,464,36,24,592,108,646,888,730,411,547,849,160,37,400,40,867,777,424,681,342,45,478,2,574,438,189,368,280,460,769,491,82,58,379,348,52,119,766,575,274,467,229,140,442,735,577,537,290,176,94,714,887,305,149,173,401,486,599,845,123,430,783,38,51,891,227,872,46,68,637,484,299,861,761,856,588,794,148,740,748,479,364,103,268,806,573,881,224,15,257,473,353,343,30,541,826,676,254,821,308,286,625,720,694,199,647,811,559,171,529,634,616,543,600,260,266,259,87,153,22,193,865,443,439,338,683,420,746,34,832,92,897,636,187,551,272,16,514,399,656,317,387,621,487,275,545,350,706,793,13,779,528,698,549,376,121,200,192,447,73,138,798,3,76,190,454,883,431,326,374,383,164,135,93,428,113,316,210,738,429,792,406,773,166,707,827,474,323,605,894,435,458,570,678,522,105,648,835,705,822,302,466,848,598,264,750,418,693,824,499,502,630,86,876,739,472,645,1,122,552,181,554,462,213,205,591,604,764,183,540,603,629,253,586,864,800,252,415,7,743,686,626,508,423,601,814,245,728,27,337,110,256,542,539,142,651,288,836,860,72,729,492,725,409,77,320,657,56,152,557,313,57,441,167,351,635,670,482,328,624,241,893,417,261,870,480,710,808,815,572,890,81,249,446,471,517,414,644,786,562,688,202,745,155,394,820,653,485,11,360,44,391,712,90,649,325,71,354,165,608,817,593,847,475,403,177,67,225,721,101,309,704,89,35,859,448,12,581,75,765,55,873,597,297,882,620,347,667,84,358,198,242,493,610,477,117,291,618,50,533,614,863,128,74,98,281,303,307,692,772,59];
    
    /** Get UNIX date value, rounded to nearest 24 hours */
    function getUnixDate (date = new Date()) {
      const DAY = 1000 * 60 * 60 * 24;
      return Math.floor(date.getTime() / DAY);
    }
    
    
    function getDailyPokemonId (date = new Date()) {
      const day = getUnixDate(date);
      const index = day % pokemonIds.length;
      return pokemonIds[index];
    }
    
    const id = getDailyPokemonId();
    console.log(id);

    Then, simply use it like this to get a "random" pokemon each day (but the ID will only change once per day):

    <PokemonDuJour id={getDailyPokemonId()} />