2

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 ?

3 Answers 3

2

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])
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.