skip to Main Content

I have stored array of objects in a state and I am using map over state to display content. whenever I click on button I get next element not the current. I don’t know why whats happening here. If someone knows please tell me the solution,

Here is my code

function App() {
  const [data, setData] = useState([
    {
      content:
        "Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae, soluta.",
    },
    {
      content:
        "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Soluta aut, commodi laboriosam, eum neque laborum itaque quidem, vel nihil sint debitis est! Aut atque itaque tempora reprehenderit illo nemo consequatur.",
    },
  ]);
  const main = useRef(null);
  function getMain() {
    console.log(main.current);
  }
  return (
    <>
      {data.map((t, i) => {
        return (
          <div key={i} className="main" ref={main}>
            <p>{t.content}</p>
            <button onClick={getMain}>mainElem</button>
          </div>
        );
      })}
    </>
  );
}

2

Answers


  1. import ReactDOM from 'react-dom';
    import React,{ useState, useRef } from 'react'
    
    
    const App = () => {
      const [items, setItems] = useState([{
        content:
          "Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae, soluta.",
      },
        {
          content:
            "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Soluta aut, commodi laboriosam, eum neque laborum itaque quidem, vel nihil sint debitis est! Aut atque itaque tempora reprehenderit illo nemo consequatur.",
        }]);
      const itemRefs = useRef([]);
      function getMain(index) {
        console.log(itemRefs.current[index]);
      }
      if (itemRefs.current.length !== items.length) {
        // Reset itemRefs.current to have refs for each item
        itemRefs.current = Array(items.length)
          .fill()
          .map((_, i) => itemRefs.current[i] || useRef(null));
      }
      return (<>Hello
        {
          items.map((t, i) => {
            return (<div key={i} className="main" ref={itemRefs.current[i]}>
              <p>{t.content}</p>
              <button onClick={()=>getMain(i)}>mainElem</button>
            </div>)
          })
        }
      </>)
    }
    
    
    
    
    
    const element = (<>
      <App />
      <h1> Hello, CodeSandbox!  </h1>
    </>);
    
    ReactDOM.render(
      element,
      document.getElementById('root')
    );
    Login or Signup to reply.
  2. Sorry, You are wrong, it’s always console.log the last item in the array.
    Because when the loop run the last time, it set the ref to the last item

    The first mistake is use a ref on to an array of items, you need to have n refs for n items

    import React, { useState, useRef } from 'react';
    import './style.css';
    
    export default function App() {
      const [data, setData] = useState([
        {
          content: 'One',
        },
        {
          content: 'Two',
        },
        {
          content: 'Three',
        },
        {
          content: 'Four',
        },
      ]);
      const main = useRef(null);
      function getMain() {
        console.log(main.current);
      }
      return (
        <>
          {data.map((t, i) => {
            return (
              <div key={i} className="main" ref={main}>
                <p>{t.content}</p>
                <button onClick={getMain}>mainElem</button>
              </div>
            );
          })}
        </>
      );
    }
    
    

    The solution:

    import React, { useState, useRef } from 'react';
    import './style.css';
    
    export default function App() {
      const [data, setData] = useState([
        {
          content: 'One',
        },
        {
          content: 'Two',
        },
        {
          content: 'Three',
        },
        {
          content: 'Four',
        },
      ]);
    
      return (
        <>
          {data.map((t, i) => {
            return <Div key={i} t={t} />;
          })}
        </>
      );
    }
    
    const Div = ({ t }) => {
      const main = useRef(null);
      function getMain() {
        console.log(main.current);
      }
      return (
        <div className="main" ref={main}>
          <p>{t.content}</p>
          <button onClick={getMain}>mainElem</button>
        </div>
      );
    };
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search