0

I'm trying to handle some star rating according to some data from an api. The problem is that I have created an array for the stars and nothing is rendered. If I console .log inside the fetchMovieDetails I can see there is data. What am I missing? I even tried var stars = useState([]) but still same result

export default function MovieDetails({ match }) {
    const [movie, setMovie] = useState({});
    var stars = [];

    useEffect(() => {
        fetchMovieDetails();
    }, []);

    async function fetchMovieDetails() {

       // get data from api

        // Handle star rating
        var rating = (response.rating/ 2).toFixed(1);

        for (var i = 0; i < 5; i++) {
            var star = {};
            if (i < ~~rating) star = 'filled';
            else if (rating % 1 === 0) star = 'half-filled';
            stars.push(star);
        }

        setMovie(response.data);
    }

    return (
        <div className="movie-container">
            <div className="movie-grid">
                <div className="movie-rating">
                    <div className="star-rating">

                        // nothing is rendered here
                        {stars.map((star) => (
                            <span className="{`icon-star ${star}`}">
                                <span className="path1"></span>
                                <span className="path2"></span>
                            </span>
                        ))}
                        {(movie.rating/ 2).toFixed(1)} / 5
                    </div>
                </div>
            </div>
        </div>
    );
}

2 Answers 2

2

I guest var stars is always re-declare. Why don't you using the useState like:

const [stars, setStarts] = useState([]);

useEffect(() => {
    fetchMovieDetails();
}, []);

async function fetchMovieDetails() {

    // get data from api

    // Handle star rating
    var rating = (response.rating/ 2).toFixed(1);
    var stars = [];
    
    for (var i = 0; i < 5; i++) {
        var star = {};
        if (i < ~~rating) star = 'filled';
        else if (rating % 1 === 0) star = 'half-filled';
        stars.push(star);
    }
    
    setStarts(stars);
    setMovie(response.data);
}
Sign up to request clarification or add additional context in comments.

2 Comments

I see, sorry still new to react and thought i could get away with some global variable in here just for the stars
Yes worked right away, just had to change the var stars to let stars
1

If you prefer to not to keep stars in the state, and if you need to move the star logic in to a separate section then useMemo will help with it.

async function fetchMovieDetails() {
     // get data from api
    .....
    setMovie(response.data);
}

const stars = useMemo(() => {
    if (!movie.rating) {
        //if movie is not fetched then return an empty array
        return [];
    }

    const rating = (movie.rating/ 2).toFixed(1);
    const starsTemp = [];
    for (let i = 0; i < 5; i++) {
        var star = {};
        if (i < ~~rating) star = 'filled';
        else if (rating % 1 === 0) star = 'half-filled';
        starsTemp.push(star);
    }

    return starsTemp;
}, [movie]); //when movie gets changed call this function

Why i prefer this is, lets say you can add a rating by clicking on a star, and then lets say you need to show the updated rating, with your approach you have to change two states, rating property of movie and the stars, so basically if a one state is depending on a another state, its better to do like this.

1 Comment

Interesting solution, i will try this

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.