Reputation: 184
I am creating an array of categories in useEffect callback, it works fine when i console.log it.
But then when I .map() it, the resulting array is empty.
import React, { useEffect } from 'react';
export const Categories = (props) => {
let categories = [];
useEffect(() => {
props.films.forEach((film) => {
if (categories.findIndex(item => item === film.category) === -1)
{
categories.push(film.category);
console.log(categories);
}
})
}, [props.films, categories])
return (
<div>
{categories.map((category) => {
return (
<div>
{category}
</div>
)
})}
</div>
);
}
Does someone have an idea ?
Upvotes: 2
Views: 2352
Reputation: 443
I think you maybe be new to react. I recommend you to take a look at React State and Lifecycle
You are using the react hook useEfect
which will be called after your component is rendered in DOM
I can think of two possible solutions to solve this
1) using the react hook useState
import React, { useEffect } from 'react';
export const Categories = (props) => {
//Make the local variable into a variable representing state
let [categories, setCategories] = useState([]);
useEffect(() => {
const result = [...categories];
props.films.forEach((film) => {
if (result.findIndex(item => item === film.category) === -1)
{
result.push(film.category);
console.log(result);
}
})
//Set the state value to trigger a re-render of your component
if(result.length !== categories.length)
setCategories(result);
}, [props.films, categories])
return (
<div>
{categories.map((category) => {
return (
<div>
{category}
</div>
)
})}
</div>
);
}
2) If re-rendering is not required, remove the useEffect
hook
import React, { useEffect } from 'react';
export const Categories = (props) => {
let categories = props.films.map(film => {
if (categories.findIndex(item => item === film.category) === -1)
{
categories.push(film.category);
console.log(categories);
}
}
return (
<div>
{categories.map((category) => {
return (
<div>
{category}
</div>
)
})}
</div>
);
}
If the useEffect react hook is required, then solution 1 is better
If there is no need to re-render the react component, then solution 2 is better
Upvotes: 0
Reputation: 2114
You should use a state value for categories:
const [categories, setCategories] = React.useState([])
useEffect(() => {
let categories = []
props.films.forEach((film) => {
if (categories.findIndex(item => item === film.category) === -1)
{
categories.push(film.category);
console.log(categories);
}
})
setCategories(categories)
}, [props.films])
Upvotes: 2
Reputation: 6049
The component is not getting re-rendered when the data in categories
is getting changed. In order to render the categories
you need to store the data using useState
.
import React, { useEffect, useState } from 'react';
export const Categories = (props) => {
const [categories, setCategories] = useState([]);
useEffect(() => {
let filmCategories = []
props.films.forEach((film) => {
if (categories.findIndex(item => item === film.category) === -1)
{
filmCategories.push(film.category);
console.log(filmCategories);
}
})
setCategories(filmCategories)
}, [props.films])
return (
<div>
{categories.map((category) => {
return (
<div>
{category}
</div>
)
})}
</div>
);
}
Hope this helps.
Upvotes: 0