Array in useState comes out empty after setting it from initial call upon component rendering.
After setting the array in the useState (and confirming it holds elements inside) the child component is rendered. Upon a user event a function in the parent component is called, and the array in the useState is printed.
However, the array comes out empty (the initial state) even though we set it and confirm in a useEffect, that it has been set.
I understand that setting useStates is a "async" event, but since this is a user event triggering the state tons of time after setting the array (which is a very small array) it still comes out empty.
As suggested in other similar questions the suggestions I have seen, is to call the array from a useEffect. However, this is not a possibility for me, since the Array has to be accessed from a function triggered by a user event.
Code:
import React, { useEffect, useState } from 'react';
const parentComponent = () => {
const [array, setArray] = useState([]);
// init useEffect
useEffect( () => {
dataBaseCall();
}, [])
useEffect( () => {
// Print database respond when setting the array
console.log(array);
}, [array])
const addObjectToArray = () => {
const objToAdd = {
onClickFunction : onClickFunction
}
// Push objToAdd into empty array
setArray( (prevState) => [...prevState, objToAdd])
}
const dataBaseCall = async () => {
Reponse can be empty array
const arrayFromDatabase = await getArrayFromDatabase("someendpoint");
if (arrayFromDatabase.length === 0) {
addObjectToArray();
} else {
// Prints [{...}, {...}, ...]
console.log(arrayFromDatabase);
// If response is not empty each obj element looks like this:
// { onClickFunction : onClickFunction }
// Print expected array once setting it in init function
setArray(arrayFromDatabase);
}
}
// Called when user clicks button in child component
const onClickFunction = () => {
// Prints empty array (inital State)
console.log(array);
}
return (
<>
{
array.length > 0 && array.map( (props) => {
return <SomeChildComponent {...props} />
})
}
</>
)
}
Child component:
import { useState } from 'react';
const SomeChildComponent= ({ onClickFunction }) => {
const [tableRows, setTableRows] = useState([])
const submitTableRow = () => {
if (tableRows.length === 0) {
// Call parent component
onClickFunction();
}
setTableRows( (prevState) => [...prevState, {...}])
}
return (
<>
<SomeInputField />
<SomeInputField />
<SomeInputField />
<SomeInputField />
<Button onClick={submitTableRow}>Submit</Button>
{
tableRows.length > 0 && tableRows.map( (row) => {
return <TableRowComponent row={row} />
})
}
</>
);
};