Reputation: 37
I am trying to create a React app that displays a list of movies and for each movie it displays the users who've watched it and if none of the users have seen it a default text would be placed that states that none of the users have seen it ,
after creating the list I've tried the approach of getting the ref of the unordered list and checking if it's children.length == 0 then the default text would be placed as a single List item ,
the code i've tried :
import React, { useRef } from "react";
function MoviesCard(props, ref) {
const usersLists = useRef(null);
// console.log(usersLists.currnet.children[1]);
return (
<li>
<h2>{props.movieName}</h2>
<p>liked by:</p>
<ul ref={usersLists}>
{props.profiles.map((profile) => {
if (profile.favoriteMovieID == props.movieId) {
return (
<li key={props.users[profile.id].name}>
{props.users[profile.id].name}
</li>
);
}
if (usersLists.current.children.length === 0) {
return <li>None of the current users liked this movie</li>;
}
})}
</ul>
{console.log(usersLists.current.children.length)}
</li>
);
}
export default MoviesCard;
Problem : when saving the project when I view it on the browser the following problem occurs :
TypeError: Cannot read property 'children' of null
I know that the ref is not set till after the function returns and the content is rendered which makes it cause problems to manipulate the DOM using useRef is there an alternative approach or a way to make the useRef.current update its value before the UI is rendered and keep observing and updating ?
Upvotes: 1
Views: 4874
Reputation: 300
One of the solutions would be as follows:
import React from "react";
function MoviesCard(props) {
const { profiles = [], movieName, movieId, users } = props;
let totalLiLength = 0;
return (
<li>
<h2>{movieName}</h2>
<p>liked by:</p>
<ul>
{profiles.map((profile) => {
if (profile.favoriteMovieID === movieId) {
totalLiLength++;
return (
<li key={users[profile.id].name}>{users[profile.id].name}</li>
);
}
})}
{totalLiLength === 0 && (
<li>None of the current users liked this movie</li>
)}
</ul>
</li>
);
}
export default MoviesCard;
Upvotes: 2
Reputation: 1156
Please try below code
import React, { useRef } from "react";
function MoviesCard(props, ref) {
const usersLists = useRef(null);
const profileIds = props.profiles.reduce((arr, profile) => {
if(profile.favoriteMovieID == props.movieId){
arr.push(profile.id);
}
return arr;
}, []);
return (
<li>
<h2>{props.movieName}</h2>
<p>liked by:</p>
<ul ref={usersLists}>
{profileIds.map((profileId) => <li key={profileId}>{props.users[profileId].name}</li>)}
{profileIds.length === 0 && <li>None of the current users liked this movie</li>}
</ul>
</li>
);
}
export default MoviesCard;
Upvotes: 1