Реагировать присваивать значения массиву

#reactjs

#reactjs

Вопрос:

Я пытаюсь обработать некоторый рейтинг звезд в соответствии с некоторыми данными из api. Проблема в том, что я создал массив для звезд, и ничего не отображается. Если я консоль.войдите в fetchMovieDetails, я вижу, что там есть данные. Чего мне не хватает? Я даже пытался var stars = useState([]) , но результат все тот же

 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>
    );
}
  

Ответ №1:

I guest var stars всегда объявляется повторно. Почему вы не используете useState, например:

 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);
}
  

Комментарии:

1. Я вижу, извините, что все еще новичок в react и подумал, что я мог бы обойтись без какой-либо глобальной переменной здесь только для звезд

2. Да, сработало сразу, просто пришлось изменить var stars на let stars

Ответ №2:

Если вы предпочитаете не сохранять звездочки в состоянии, и если вам нужно перенести логику звездочек в отдельный раздел, то useMemo поможет с этим.

 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
  

Почему я предпочитаю это, допустим, вы можете добавить рейтинг, нажав на звездочку, а затем, допустим, вам нужно показать обновленный рейтинг, при вашем подходе вам нужно изменить два состояния, rating свойство movie и stars , так что в принципе, если одно состояние зависит от другого состояния, лучше сделать так.

Комментарии:

1. Интересное решение, я попробую это