Kevvv
Kevvv

Reputation: 4023

useRef object returning undefined in React/React-Native

I'm getting undefined when I try to access the ref object. I'm mapping an array of images and attempting to access individual ones through useRef.

First, I initialized the useRef as following:

const gridImages = useRef([React.createRef(), React.createRef()])

And then mapping of the images:

<View style={styles.grid}>
    {images.map((src, index) => {
        const style = index === activeIndex ? activeIndexStyle : undefined
        return (
            <TouchableWithoutFeedback key={index} onPress={() => handleOpenImage(index)}>
                <Animated.Image 
                    source={{ uri: src }}
                    style={[ styles.gridImage, style ]}
                    ref={gridImages.current[index]}
                />
            </TouchableWithoutFeedback>
        )
    })}
</View>                

When I invoke the following method, I get an error saying

undefined is not an object (evaluating 'gridImages.current[index].getNode')

When I console.log the object gridImages.current shows the methods with no problem, but as soon as I include the index, I get the undefined error.

const handleOpenImage = index => {
    console.log(gridImages.current[index])
    gridImages.current[index].getNode().measure((x, y, width, height, pageX, pageY) => {
        position.setValue({
            x: pageX,
            y: pageY,
        })

        size.setValue({
            x: width,
            y: height,
        })
        setActiveImage(images[index])
        setActiveIndex(index)
    })
}

Upvotes: 0

Views: 1767

Answers (1)

skovy
skovy

Reputation: 5650

I believe the issue is that you need to have another .current after the index.

For example: gridImages.current[index].current since you're using both useRef and React.createRef

Here is a simplified code sample with only the critical pieces (please excuse the conversion to ReactDOM instead of React Native but the principles should still be identical):

function Comp(props) {
  const { images } = props;
  const gridImages = React.useRef(images.map(_ => React.createRef()));

  const handleClick = index => {
    console.log(gridImages.current[index].current);
  };

  return (
    <div>
      {images.map((src, index) => (
        <img
          onClick={() => handleClick(index)}
          src={src}
          key={index}
          ref={gridImages.current[index]}
        />
      ))}
    </div>
  );
}

function App() {
  return (
    <Comp
      images={[
        "https://placekitten.com/100/100",
        "https://placekitten.com/101/101",
        "https://placekitten.com/102/102"
      ]}
    />
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

Note, I also updated the useRef portion to be dynamic based on the number of images since that seems to be dynamic in a way suggested in this answer: https://stackoverflow.com/a/55996413/2690790

Upvotes: 1

Related Questions