menu

Questions & Answers

Changing image based on index, using ImageId

I'm using street views from Mapillary.js and depending on an image key, passed as a prop, I want to show different images/street views. I've tried to do it with a conditional (ternary) operator like this:

<Mapillary width="auto" height="94vh" imageId={currentClue === 0 ? '2978574139073965' : currentClue === 1 ? '461631028397375' : currentClue === 2 ? '2978574139073965' : currentClue === 3 ? '312627450377787' : currentClue === 4 ? '695710578427767' : ''} />

Right now though, I only see the first image (when currentClue === 0). When currentClue === 1, the first image is still showing, although I can see in the console that the currentClue index is ascending.

I've also tried to change image by saving imageId in state and using it like this:

  const handleClick = () => {
    setCurrentClue(currentClue + 1);
    if (currentClue < 4) { //*  Show alert if clue index > 4
      setLevel(level - 1);
      if (currentClue === 1) setImageId('461631028397375')
      if (currentClue === 2) setImageId('2978574139073965')
    } else {
      swal('Time to make a guess!', {
        button: 'OK'
      });
    }
    dispatch(game.actions.setScore(currentScore - 1));
  };
But get the same result: First image is showing, but not the second. Does anyone have any suggestions on how to get it to work?

This is the whole component where I'm trying to do this:

import React, { useState, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { game } from 'reducers/game';
import swal from 'sweetalert';

import { Mapillary } from 'components/Mapillary/Mapillary';
import { Paragraph } from 'GlobalStyles';
import { MapillaryContainer, ClueContainer, SpecialSpan, ClueParagraph, AnotherClueButton } from './Clues.Styles'

export const Clues = () => {
  const [games, setGames] = useState([])
  const [loading, setLoading] = useState(false);
  const [currentClue, setCurrentClue] = useState(0);
  const [level, setLevel] = useState(5);
  // const [imageId, setImageId] = useState('2978574139073965')

  //* Fetching clues
  const fetchClues = () => {
    setLoading(true);
    fetch('https://final-project-api-veooltntuq-lz.a.run.app/games')
      .then((response) => {
        return response.json()
      })
      .then((response) => {
        setGames(response.games)
      })
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  }

  //* Setting current score
  const currentScore = useSelector((store) => store.game.score);
  const dispatch = useDispatch();

  const handleClick = () => {
    setCurrentClue(currentClue + 1);
    if (currentClue < 4) { //*  Show alert if clue index > 4
      setLevel(level - 1);
    /*     if (currentClue === 1) setImageId('461631028397375')
      if (currentClue === 2) setImageId('2978574139073965') */
    } else {
      swal('Time to make a guess!', {
        button: 'OK'
      });
    }
    dispatch(game.actions.setScore(currentScore - 1));
  };

  useEffect(() => {
    fetchClues()
  }, [])

  const activeClue = games[currentClue];

  if (loading) {
    return <Paragraph>Loading clues...</Paragraph>
  }

  if (currentClue < 5) { //* Stop showing clues after clue 5
    return (
      <div>
        <MapillaryContainer>
          {console.log(currentClue)}
          <Mapillary width="auto" height="94vh" imageId={currentClue === 0 ? '2978574139073965' : currentClue === 1 ? '461631028397375' : currentClue === 2 ? '2978574139073965' : currentClue === 3 ? '312627450377787' : currentClue === 4 ? '695710578427767' : ''} />
        </MapillaryContainer>
        <ClueContainer>

          <SpecialSpan>Level: {level}</SpecialSpan>
          <ClueParagraph>{activeClue && activeClue.gameOne}</ClueParagraph>

          <AnotherClueButton type="button" onClick={() => handleClick()}>I need another clue</AnotherClueButton>
        </ClueContainer>
      </div>
    )
  }
}

Comments:
2023-01-07 20:38:04
You will have to post what the Mapillary component does. Perhaps it is only using the imageId at load time, and after then ignores changes to it. Does it work if you add key={currentClue} ? Although this might be bad for performance depending on what that component does, and how often the currentClue changes.
Answers(1) :

I think your second method will be work, the error is that you are adding and checking the currentClue value in the same function, your state is not updated, you have to use useEffect it will detect the change of currentClue state and change the image according to your state value, I hope it works.

here is one more thing you just need to handle the dispatch according to your requirements because useEffect will be called once your component load.

const handleClick = () => {
    const val = currentClue + 1;
    setCurrentClue(val);
};

useEffect(() => {
    if (currentClue < 4) { //*  Show alert if clue index > 4
    setLevel(level - 1);
    if (currentClue === 1) setImageId('461631028397375')
    if (currentClue === 2) setImageId('2978574139073965')
    } else {
    swal('Time to make a guess!', {
        button: 'OK'
    });
    }
    dispatch(game.actions.setScore(currentScore - 1));
}, [currentClue])