Ad

How Can You Make A CreateRef/useRef Not Target The Last Value. But Rather Go To Where Its Suppose To

Can't manage to make useRef/createRef to get any other div's other then what was added last. How can i make it so when the button is clicked the ref to the div changes.

I've tried with both useRef and createRef. Since I want to make a new instance of ref, i've looked more into createRef rather then useRef. I've also played around useEffect. But my solution didn't help me with my biggest problem

I have made a small project containing 3 components to help you understand what I'm trying to explain.

I also have a database containing mock data -> in my real project this isn't the problem. It's an array containing objects. [{'id':'1', 'name':'first'},...]

Main:

const MainComponent = () => {
    const dataRef = React.createRef(null) 

    React.useEffect (() => {
        if(dataRef && dataRef.current){
            dataRef.current.scrollIntoView({ behavior:'smooth', block:'start' })
       }
    },[dataRef])

    const _onClick = (e) => {
        dataRef.current.focus(); 
    }

    return(
        <>
        {data && data.map((entry, index) =>{
            return <ButtonList 
                key={index}
                entry={entry}
                onClick={_onClick}
            /> 
        })}

        {data && data.map((entry, index) =>{
            return <ListingAllData  
                key={index}
                dataRef={dataRef}
                entry={entry}
                index={index}/>
        })}
        </>
    )
}

Button Component

const ButtonList = ({ entry, onClick }) => {
    return <button onClick={onClick}>{entry.name}</button>
}

Listing data component

const ListingAllData = (props) => {
    const {entry, dataRef } = props; 
    return (
        <div ref={dataRef}>
            <p>{entry.id}</p>
            <p>{entry.name}</p>
        </div>
    );
}

I've console logged the data.current, it only fetches the last element. I hoped it would fetch the one for the button I clicked on.

Ad

Answer

I think the main idea here is to create dynamic refs for each element (array of refs), that's why only the last one is selected when app renders out.

const MainComponent = () => {
  const dataRefs = [];

  data.forEach(_ => {
    dataRefs.push(React.createRef(null));
  });

  const _onClick = (e, index) => {
    dataRefs[index].current.focus();
    dataRefs[index].current.scrollIntoView({
      behavior: "smooth",
      block: "start"
    });
  };

  return (
    <>
      {data &&
        data.map((entry, index) => {
          return (
            <ButtonList
              key={index}
              entry={entry}
              onClick={e => _onClick(e, index)}
            />
          );
        })}

      {data &&
        data.map((entry, index) => {
          return (
            <>
              <ListingAllData
                key={index}
                dataRef={dataRefs[index]}
                entry={entry}
                index={index}
              />
            </>
          );
        })}
    </>
  );
};

Created working example in code sandbox.

https://codesandbox.io/s/dynamic-refs-so25v

Ad
source: stackoverflow.com
Ad