1

I have read through a lot of different types of solutions here but none seem to be quite what I need.

I am trying to change the variable "currentIndex" when a user clicks the image.

Right now the change reaches inside the onClick function but does not change the outside variable. Not sure what I am doing wrong.

My end goal is to have user be able to click an thumbnail image and have it change the main image. If there is a better way PLEASE I am open to that.

const gallery = 
  product.images.length > 1 ? (
    <Grid gap={2} columns={4}>
      {product.images.map((img, index) => (
        <Thumbnail 
          image={img}
          key={img.id}
          alt={product.title}
          index={index}
          onClick={() => changeImage(index)}
        />
      ))}
    </Grid>
  ) : null;

let currentIndex = 0;

let changeImage = function(index) {
  currentIndex = index;

  console.log("currentindex inside changeImage Function is: " + currentIndex) // This returns the current index of the image clicked as it should.

  return currentIndex;
}

console.log("currentindex outside changeImage Function is: " + currentIndex)// This returns "0" still

Code below is for main image.

<div>
  {console.log('currentindex inside return is: ' + currentIndex)}//This returns 0 as well still

  <GatsbyImage
    image={product.images[currentIndex].gatsbyImageData}
    alt={product.title}
  />          
  <div>
    {gallery}
  </div>
</div>

Not sure if this code is needed but below is the code for the "Thumbnail" element

/** @jsx jsx */
import { jsx } from 'theme-ui'
import { GatsbyImage } from 'gatsby-plugin-image'

export const Thumbnail = ({ image, onClick, alt, index }) => {

  return (
    <button
      sx={{
        cursor: "pointer",
        border: "none",
        padding: "2px",
        backgroundColor: "white",
      }}
      onClick={onClick}
    >
      <GatsbyImage
        image={image.gatsbyImageData}
        alt={alt}
      />
    </button>
  )
}

krichey15
  • 591
  • 6
  • 14
  • The `console.log` statement that returns 0 only ever runs when the page is first loaded. The only code that runs when the click is handled is that inside the `changeImage` function – Tibrogargan Apr 19 '22 at 23:38
  • @Tibrogargan there are two that return 0. Shouldn't the currentIndex variable change after function has run. If not. Why not? – krichey15 Apr 19 '22 at 23:43
  • 2
    I'm not familiar with Gatsby but I'm quite sure what you want is a state update. Wouldn't useState solve your issue easily? – George Makroglou Apr 19 '22 at 23:45
  • 2
    That comment goes for all code in your page. Code attached to DOM objects only ever fires due to the occurrence of an event. The page being loaded is an event, so all the code on the page that's at a global level (i.e. code at the root level of script tags and anything embedded in your HTML) will all run at that time and never again. – Tibrogargan Apr 19 '22 at 23:46

1 Answers1

3

Right now you are trying to update currentIndex with let currentIndex = 0;. In React you will want to use state to keep track of currentIndex so that your other components (such as the main image) can changed based on currentIndex.

Instead of let currentIndex = 0;, initialize currentIndex with useState like this:

const [currentIndex, setCurrentIndex] = useState(0);

Make sure to import useState as well: import {useState} from 'react';

Then you can change your changeImage function to set the state of currentIndex like this:

let changeImage = function(index) {
  setCurrentIndex(index);
}

Why do it this way? Because you need to trigger a rerender to use the newly updated currentIndex anywhere. Code that is part of a component is only run once unless a state update occurs in that component or in a parent, which is why the console.logs and the Image weren't updating.

Andrew Hulterstrom
  • 1,563
  • 4
  • 18