I'm using a useEffect hook in React that has to update state based on the dependencies, and I added a variable isMounted that is set to false on cleanup, and any functions that are async or affect state are only called if isMounted evaluated to true. I'm not sure where the memory leak is coming from aside from that it's being caused by the useEffect hook in this component.
Here are the parts of the component that might be causing the memory leak.
(i know i should be using constant variables for the rating color its a WIP)
const ContentItem = ({ contentItem, type, showComment, allowDelete, isList }) => {
const [ratingColor, setRatingColor] = useState('rgb(58,58,58)');
const [content, setContent] = useState({});
const [awaitingItem, setAwaitingItem] = useState(true);
const [owner, setOwner] = useState(null);
const user = useSelector(state => state.userReducer.user);
const token = useSelector(state => state.userReducer.token);
const dispatch = useDispatch();
const history = useHistory();
const getOwner = useCallback(
async (id) => {
try {
const { user } = await YetiApi.getUserById(id);
setOwner(user);
}
catch (errs) {
dispatch(showErrors(errs));
}
}, [dispatch]);
const getPost = useCallback(
async () => {
try {
const { post } = await YetiApi.getPost(token, contentItem.id);
setContent({
id: post.id,
body: post.body,
userId: post.user_id,
rating: post.rating,
owner
});
getOwner(post.user_id);
setAwaitingItem(false);
}
catch (errs) {
dispatch(showErrors(errs));
}
}, [dispatch, contentItem.id, getOwner, owner, token]);
const getComment = useCallback(
async () => {
try {
const { comment } = await YetiApi.getComment(token, contentItem.id);
setContent({
id: comment.id,
body: comment.comment,
userId: comment.user_id,
postId: comment.post_id,
rating: comment.rating,
owner
});
getOwner(comment.user_id);
setAwaitingItem(false);
}
catch (errs) {
dispatch(showErrors(errs));
}
}, [dispatch, contentItem.id, getOwner, owner, token]);
// memory leak for some reason, can't figure out why
useEffect(() => {
let isMounted = true;
const getRatingColor = () => {
switch (content.rating) {
case content.rating < 0:
setRatingColor('red');
break;
case content.rating > 0:
setRatingColor('green');
break;
default:
setRatingColor('rgb(58,58,58)');
break;
}
}
if (content.body && isMounted) getRatingColor();
if (!owner && isMounted) getOwner(contentItem.user_id);
if (isMounted && !content.body) {
switch (type) {
case 'post':
getPost();
break;
case 'comment':
getComment();
break;
default:
break;
}
}
return () => {
isMounted = false;
}
}, [
contentItem.rating, contentItem.user_id,
owner, dispatch,
contentItem, content.body,
content.rating,
getComment, getPost,
getOwner, type
]);
// do something
return (<SOME_JSX />);
}
There's a lot going on I know so if there's anything that I can definitely remove from the code snippet, or explain more thoroughly please let me know!