0

In first file Create.js (sorry for no refactoring code)

I have array with useRef() values,
it is updated as excepted:

const [refsArr, setRefsArr] = useState([]);

useEffect(() => {
    setRefsArr([
      { fromAddress },
      { fromCity },
      { fromPC },
      { fromCountry },
      { toCName },
      { toAddress },
      { toCity },
      { toPC },
      { toCountry },
      { desc },
    ]);
  }, []);

Also I have items.map() (short version, some props and container missing),
which include CreateItem component, and also button which create new item for list inside big form (you can see app here)

 {itemsList.map((item, itemIndex) => {
              return (
    enter code here
                <CreateItem
                  key={item.id}
                  setRefsArr={setRefsArr}
                  refsArr={refsArr}    />
           <button
                onClick={() => {
                   setItemsList([...itemsList, { id: itemsList.length + 1 }]);
                 }}
                 className="btn-create-item"
            >
                 + Add New Item
             </button>
            )
  })}  

and also there is CreateItem.js with useEffect with intention to update refsArr

useEffect(() => {
  setRefsArr([...refsArr, [{ itemNameRef, qtyRef, priceRef }]]);
}, []);

but after intial render (app is loaded first time), useEffect() from CreateItem doesn't update refsArr.
It is updated after click on button. So I am puzzled how to update my refsArr initially?

2 Answers2

3

Your dependency array for the useEffect is empty. A useEffect fires on three occasions:

  • component mounts
  • dependency changes
  • component unmounts (return value is executed)

In your case, an empty deps array means the useEffect will only fire once on component mount (No dependency array will fire every re-render). For example adding deps here will trigger the useEffect when the component re-renders:

useEffect(() => {
  setRefsArr([...refsArr, [{ itemNameRef, qtyRef, priceRef }]]);
}, [priceRef]);

Note: A re-render only occurs when component state changes ie params, hooks, and state. useState triggers a re-render, useRef does not trigger a re-render. Once you research these hooks more, you'll realize having a useState value contain an array of Refs is non-sensical. https://reactjs.org/docs/hooks-reference.html

However, I see many other issues with your code. You should not suffix a state value with the word 'Ref', this is confusing because it is not a Ref. You should probably be using useContext hook here to manage component state instead of passing along a setState function. And most importantly having a useEffect be responsible for updating component state instead of callback methods on an element like input onChange is a recipe for disaster.

Bugbeeb
  • 2,021
  • 1
  • 9
  • 26
  • thank you for your time bugbeeb, i gave you upvote even i am not sure you are helpful for my problem :) i use ref naming to variables which contain useRef(). i am not trying to trigger a re-render with useRef() and because of that my dependecy array is empty, i have problems mainly with items which are stored from my localstorage. (maybe i was not clear enough with that in my explanation). but i am not sure why refsArr is not update intially via useEffect in itemList but works regularly with events. – Nikola Golubović Nov 26 '21 at 16:17
0

Solved my problem simply with

setRefsArr((prevArr) => [...prevArr, [{ itemNameRef, qtyRef, priceRef }]]);

Further explanation:

useState set method not reflecting change immediately