I am experiencing a problem that when I call the "map" function to iterate over a array of objects that was created using useState, I get a error saying that "map" is not a function.
It works fine if I use it on a manuually defined array like `const array = [a, b, c] but when using useState, it does not.
I created the array like this (Notice that I only pasted the parts that are actually doing this.)
// Etc
async function getFicharpgs(login_usuario) {
// Step 1 - Get my JSON Data from my API.
try {
const response = await axios({
method: "post", url: "http://localhost:3000/usuario_ficharpg/listar_fichas", data: {"login": login_usuario}
});
// Console Log prints perfectly (Printed image below.)
console.log('getFicharpgs => Resposta completa:', response);
console.log('getFicharpgs => Lista de Fichas do Usuário Recebida:', response.data);
return response; // This returns my response data, including my JSON Data.
// Etc
function Ficharpg({objeto_props}) {
const {login_usuario} = objeto_props;
// Step 2 - Create my array list as a state variable to be passed on to another component
const [ficharpgs, setFicharpgs] = useState([]);
// Etc
useEffect(() => {
// Step 3 - Pass the data I got from my getter to my useState array.
if (login_usuario) {
// Espera a função assíncrona getUsers ser concluída antes de finalizar o efeito (Renderizar o Componente).
getFicharpgs(login_usuario)
// Implantacoes de Then/Catch para resolver "Promise Ignorada" e fazer regras de negocio.
.then(response => {
// Entra aqui caso o nosso status tenha sido 200 - [Object object]
console.log(`Componente Ficharpg => Fichas de RPG do Usuario Recebidas com sucesso. Status: ${response.status}`);
// Mudo o estado para dizer que o carregamento dos dados terminou
setdadosCarregando(false);
// Here is where I add my data from my response into the state variable.
setFicharpgs(response.data); // Step 3 Completed here.
// Etc
// Render the data from my useState array.
return (<div>
{/* If Ternario que checa se os dados estao sendo carregados. */}
{dadosCarregando ? (<p>Selecione qual usuário vai mostrar as fichas.</p>) : (<table>
<thead>
<tr>
<th>Fichas de RPG do Usuario {login_usuario}</th>
</tr>
<tr>
<th>Nome</th>
<th>Classe</th>
<th>Raca</th>
<th>Nivel</th>
<th>Alinhamento</th>
</tr>
</thead>
<tbody>
{/* Step 4 - Iterate over my list and print my objects. */}
{ficharpgs.map((ficharpg, ficharpg_id) => (
// Index Key: ID da Ficha do RPG, identificador da nossa "linha" (Table Row) - Key => Built-In Do JavaScript.
<tr key={ficharpg_id}>
<td>name: {ficharpg.nome}</td>{" "}
<td>age: {ficharpg.classe}</td>
<td>age: {ficharpg.raca}</td>
<td>age: {ficharpg.nivel}</td>
<td>age: {ficharpg.alinhamento}</td>
</tr>
))}
// Etc
So, at step 4, I was expecting it to print my data from the array, but instead, I am getting the following error:
ficharpgs.map is not a function
TypeError: ficharpgs.map is not a function
I already tried to look into another posts from users that had the same problems, like this one:
ReactJs useState .map() is not a function
But I was not able to fix it reading the answer from it. 🙁
Edit
Just a quick edit, here is the output of a console.log from inside my getter function that prints the response itself:
And this is the output of a console.log from inside my component, that prints my useState array:
2
Answers
This is a common error that happens when the variable you referred to is not an array.
map()
is a method of an array, so if the variable is not an array, it will throw this error.As your screenshot says, the response of
getFicharpgs()
API call is an object, not an array.So, you need to get the correct array:
The issue is timing.
When the component loads its is performing an async axios request for data, while this is happening the component continues to load which means it is encountering the map iterator before the axios call has returned and the
ficharpgs
state has actually been set. You are effectively trying to call map() on undefined.The solution is to check the state before trying to iterate:
This ensures when the component first loads and the
ficharpgs
state is the default value (in this case undefined) map is ignored. When the axios call returns and theficharpgs
state is updated, the update causes the component to refresh and provided thatficharpgs
now has a value, map is actioned.