每当运行删除函数时,React组件内存泄漏..不使用useEffect



预览:https://befreebucket.s3.us-east-2.amazonaws.com/beFree-5fc1c2a00cb53d0017972145-kebin1421-hotmail-com-1615773766297.gif

我目前有一个配置文件组件作为父组件;所述组件具有以下代码:

const [profile, setProfile] = useState(null)
const [posts, setPosts] = useState([])
useEffect(() => {
getProfile(match.params.id)
.then((result) => {
//  Set the user
setProfile(result.payload.data)
// Get posts by user
getPosts(`?user=${match.params.id}`)
.then((result) => {
setPosts(result.payload.data)
})
.catch((err) => {
console.log('Posts error' + err)
})
})
.catch((err) => {
console.log('User error' + err)
})
}, []);

然后,所有这些数据被传递到Single组件中,该组件是子组件

posts?.length > 0 ? (
posts.map((post, index) => (
<Single
key={post._id}
post={post}
postId={postId}
setObjects={setPosts}
objects={posts}
setTotalResult={setTotalResults}
/>
))
)

当我从Single组件中的动态组件触发删除函数时,问题就出现了。包含此函数的组件在Single组件中如下所示:

import React, { useEffect, useState, useContext } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
// ACTIONS
import { deletePost } from '../../../actions/post';
// HELPERS
import ConfirmModal from '../../layout/ConfirmModal';
import ContentLoader from '../../layout/ContentLoader';
import { formatDate } from '../../../helpers/utilities';
import UseImage from '../../layout/UseImage';
// REACTBOOTSTRAP
import Card from 'react-bootstrap/Card';
import Carousel from 'react-bootstrap/Carousel';
import Dropdown from 'react-bootstrap/Dropdown';
import DropdownButton from 'react-bootstrap/DropdownButton';
import Button from 'react-bootstrap/Button';
import Badge from 'react-bootstrap/Badge';
const Single = ({
deletePost,
post: {
_id,
user,
postedto,
postedfrom,
text,
images,
hidden,
likes,
sharedby,
createdAt
},
postId = null,
setObjects,
objects = [],
setTotalResults,
auth
}) => {
const hasLike = likes?.map((like) => like.user).includes(auth.user.data._id);
const hasShare = sharedby
?.map((share) => share.user)
.includes(auth.user.data._id);
const [liked, setLiked] = useState(false); // Done
const [likedIcon, setLikedIcon] = useState(`fas fa-heart`); // Done
const [likesQuantity, setLikesQuantity] = useState(0); // Done
const [, setShared] = useState(false);
const [sharedIcon, setSharedIcon] = useState(`far fa-share-square`);
const [sharesQuantity, setSharesQuantity] = useState(0);
const [hiden, setHidden] = useState(false);
const [hiddenIcon, setHiddenIcon] = useState(`fas fa-eye`);
const [, setError] = useState(false);
useEffect(() => {
setLiked(hasLike);
setLikedIcon(hasLike ? `fas fa-heart` : `far fa-heart`);
setLikesQuantity(likes?.length);
setShared(hasShare);
setSharedIcon(hasShare ? `fas fa-share-square` : `far fa-share-square`);
setSharesQuantity(sharedby?.length);
setHidden(hidden);
setHiddenIcon(hidden ? `fas fa-eye-slash` : `fas fa-eye`);
}, []);
return _id === null || _id === undefined ? (
<ContentLoader />
) : (
<article className={`${_id ? _id : postId} mb-3`}>
<Card>
<Card.Header>
<div className={``}>
<Link
to={`/profiles/${user._id ? user._id : auth.user.data._id}/posts`}
>
<UseImage
src={`${user.avatar ? user.avatar : auth.user.data.avatar}`}
alt={`${
user.username ? user.username : auth.user.data.username
}`}
classGiven={`w-auto mr-2`}
style={{
height: '35px',
objectFit: 'cover'
}}
/>
{user.username === auth.user.data.username
? 'You'
: user.username
? user.username
: auth.user.data.username}
</Link>
{postedto && (
<>
{` `}posted to{` `}
<Link
to={`/profiles/${postedto._id}/posts`}
className={`ml-1 mr-1`}
>
{postedto.username}
</Link>
</>
)}
{postedfrom && (
<>
{' '}
shared from{' '}
<Link to={`/profiles/${postedfrom._id}/posts`}>
{postedfrom.username}
</Link>
</>
)}
<div className={`float-right`}>
<DropdownButton
alignRight
variant={`secondary`}
size={`sm`}
drop={`down`}
id={`dropdown-basic-button`}
title={<i className={`fas fa-ellipsis-h`} />}
>
{user._id === auth.user.data._id && (
<>
<Dropdown.Divider />
<ConfirmModal
id={_id ? _id : postId}
action={deletePost}
classStr={`dropdown-item`}
setObjects={setObjects}
objects={objects}
setTotalResults={setTotalResults}
/>
</>
)}
</DropdownButton>
</div>
</div>
</Card.Header>
<Card.Body
className={`p-0`}
>
{images.length > 1 ? (
<>
<Carousel style={{ position: 'sticky' }}>
{images.slice(0, 5).map((image, index) => (
<Carousel.Item key={index} className={`${index}`}>
<UseImage
src={`${image}`}
alt={``}
classGiven={`p-0 d-block w-100`}
width={`auto`}
height={`auto`}
style={{ objectFit: 'fill' }}
/>
</Carousel.Item>
))}
</Carousel>
<h6 className={`position-absolute images-length-badge`}>
<Badge pill variant={`light`}>
{images.length}
</Badge>
</h6>
</>
)}
</Card.Body>
<Card.Footer className={`p-1`}>
<div className={`float-left`}>
{user._id !== auth.user.data._id && (
<Button
variant={`link`}
size={`sm`}
className={`mr-1`}
>
<i className={`${likedIcon} mr-1`} />
<span>{likesQuantity}</span>
</Button>
)}
<Link
to={`/posts/${_id ? _id : postId}`}
className={`btn btn-link btn-sm mr-1`}
>
<i className={`far fa-comment mr-1`} />
Comment
</Link>
{user._id !== auth.user.data._id && (
<Button
variant={`link`}
size={`sm`}
className={`mr-1`}
>
<i className={`${sharedIcon} mr-1`} />
<span>{sharesQuantity}</span>
</Button>
)}
</div>
<div className={`float-right`}>
{formatDate(createdAt, 'hours') + ' hours ago'}
</div>
</Card.Footer>
</Card>
</article>
);
};
Single.propTypes = {
deletePost: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired
};
const mapStateToProps = (state) => ({
auth: state.auth
});
export default connect(mapStateToProps, {
deletePost,
})(Single);

最后,在deleteObject:的名称下找到了触发ConfirmModal组件内存泄漏的函数

import React, { useState } from 'react';
// ACTIONS
// HELPERS
// REACTBOOTSTRAP
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
const ConfirmModal = ({
id = null,
sId = null,
location = ``,
as = `button`,
classStr = ``,
action,
action2,
setObjects,
objects = [],
setTotalResults
}) => {
const [confirmDeleteModal, setConfirmDeleteModal] = useState(false);
const [, setError] = useState(false);
const openDeleteModal = (e) => {
setConfirmDeleteModal(true);
};
const closeDeleteModal = (e) => {
setConfirmDeleteModal(false);
};
const deleteObject = async (e) => {
e.preventDefault();
await action(id, sId)
.then((result) => {
if (sId) {
setObjects(objects.filter((object) => object._id !== sId));
} else {
setObjects(objects.filter((object) => object._id !== id));
}
setTotalResults(objects.length - 1);
if (typeof action2 === `function`) {
action2(location)
.then((result) => {
console.log(`Done`);
})
.catch((err) => {
setError(true);
});
}
})
.catch((err) => {
setError(true);
});
};
return (
<>
<Button
variant={`danger`}
size={`sm`}
onClick={openDeleteModal}
data-target={`deleteModal#${id}`}
as={as}
className={classStr}
>
<i className={`fas fa-trash-alt mr-1`} />
Delete
</Button>
{confirmDeleteModal && (
<Modal
show={true}
onHide={closeDeleteModal}
backdrop={true}
animation={true}
size={`sm`}
id={`deleteModal#${id}`}
>
<Modal.Header closeButton>
<Modal.Title>Are you sure?</Modal.Title>
</Modal.Header>
<Modal.Body>{id}</Modal.Body>
<Modal.Footer>
<Button
variant={`secondary`}
size={`sm`}
onClick={closeDeleteModal}
>
Close
</Button>
<Button
type={`submit`}
size={`sm`}
onClick={deleteObject}
variant={`primary`}
>
Submit
</Button>
</Modal.Footer>
</Modal>
)}
</>
);
};
export default ConfirmModal;

你们中有人知道如何解决这个问题吗?我已经处理这个问题大约三个星期了,只是想确定它是从哪里来的。

事实证明,我的错误是忘记在Single组件和ConfirmModal:所需的道具中键入s

posts?.length > 0 ? (
posts.map((post, index) => (
<Single
key={post._id}
post={post}
postId={postId}
setObjects={setPosts}
objects={posts}
// setTotalResult={setTotalResults}
setTotalResults={setTotalResults}
/>
))
)

最新更新