title: Adding a key-value pair to an object inside loop using React useState hook
body: <p>I'm trying to add a key-value pair to an object using <code>useState</code> inside <code>map</code> function. However, the spread operation in <code>setContainer({...container, [data.pk]: data.name});</code> seems to be ineffective.</p>
  <p>The code snippet below exactly illustrates the problem that I'm trying to solve. In fact, in my original code <code>container</code> is declared at another <em>ContextProvider</em> component and referenced using <code>useContext</code>, but I replaced it with <code>useState</code> for simpliticy.</p>
  <p>I guess it has to do with the asynchronous nature of <code>setState</code> hook, but I don't fully understand what's going on under the hood.</p>
  <p>Please let me know what is causing this issue and how to yield the outcome I expected.
  Thank you.</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="true">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>const {useState, useEffect} = React;
  
  const myData = [{pk: 1, name:'apple'},
                  {pk: 2, name:'banana'},
                  {pk: 3, name:'citrus'},
  ]
  
  const Example = () =&gt; {
    const [container, setContainer] = useState({});
    
    useEffect(()=&gt;{
        myData.map(data=&gt;{
          console.log(`During this iteration, a key-value pair (key ${data.pk} and value '${data.name}') should be added to container`);
              setContainer({...container, [data.pk]: data.name});
        })
    }, [])
  
    return (
      &lt;div&gt;
        &lt;div&gt;result I expected: {"{'1': 'apple', '2': 'banana','3': 'citrus'}"}&lt;/div&gt;
        &lt;div&gt;result: {JSON.stringify(container)}&lt;/div&gt;
      &lt;/div&gt;
    );
  };
  
  // Render it
  ReactDOM.render(
    &lt;Example /&gt;,
    document.getElementById("react")
  );</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"&gt;&lt;/script&gt;
  &lt;div id="react"&gt;&lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  <h1>Update</h1>
  <p>The main reason I wanted to use <code>useState</code> in loops was to use the state as a container of <code>refs</code> of components. However, I found it inefficient to do so, because it caused too many rerenders and was hard to determine when the loop finished. After a lot of searching, I ended up declaring <code>useRef({})</code> in the Context Provider and use it as a refs container (which seems to fit the actual purpose it was created I guess). The refs container can be used as following:</p>
  <pre><code>const refsContainer = useRef({});
  </code></pre>
  <pre><code>import React from 'react';
  
  const Notes = () =&gt; {
      const setRef = (noteId) =&gt; (element) =&gt; {
          refsContainer.current[noteId] = element
      };
      return (
          &lt;Masonry&gt;                     
              {pubData?.map(publication =&gt; {                                                                              
                  return &lt;PublicationCard innerRef={setRef(publication.noteId)}/&gt;   
              })}                                                                                                         
          &lt;/Masonry&gt;                                                                                                      
      );
  };
  
  export default Notes;
  </code></pre>
  <pre><code>const pubCardRef = refsContainer.current[rank.note.noteId];
  window.scrollTo({top: pubCardRef?.offsetTop - 80, behavior: 'smooth'})
  </code></pre>