Reputation: 3521
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>
);
}
Upvotes: 0
Views: 146
Reputation: 21901
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.
Upvotes: 1
Reputation: 1951
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);
}
Upvotes: 2