#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. Интересное решение, я попробую это