使用 useSelector 钩子将每个子 React 组件的状态分开

Separate states per child React component with useSelector hook

我有一个加载图像的应用程序,我想单击 'Like' 和图像的竖起大拇指图标或垃圾桶图标来删除图像。当对后端的调用挂起时,我想显示一个微调器而不是图标。当从商店获取我的调用的加载状态时,我的所有组件都会同时更新,而不是仅仅针对我正在单击的当前组件

看起来像这样(点击赞按钮后出现微调器)

如您所见,每个 ImageCard!!!

上都出现了微调器

ImageCard.tsx

export function ImageCard({ image }: ImageProp): ReactElement {
    const [liked, setLiked] = useState(image.tags.includes(TAGS.FAV));
    const imageLikeState = useSelector(likeImagePending);
    const imageDeleteState = useSelector(deleteImagePending);

    const dispatch = useDispatch();
    const like = (public_id: string, tag: string) => {
        setLiked(!liked);
        dispatch(toggleLiked(public_id, tag));
    };
    const deleteImage = (public_id: string) => {
        dispatch(deleteImageCall(public_id));
    };

    return (
        <div className="card mb-5 portfolio-item">
            <div className="card-image">
                <img className="image" src={image.secure_url} alt="" />
            </div>
            <div className="card-button-container">
                {!imageDeleteState && (
                    <FontAwesomeIcon
                        onClick={() => deleteImage(image.public_id)}
                        icon={trashRegular}
                        size="lg"
                        color="#FF4545"
                    />
                )}

                {imageDeleteState && <img className="spinner" src={Spinner} alt="Loading Spinner" />}

                <div className="rating-container">
                    <FontAwesomeIcon icon={starRegular} size="lg" color="#FF9529" />
                    <FontAwesomeIcon icon={starRegular} size="lg" color="#FF9529" />
                    <FontAwesomeIcon icon={starRegular} size="lg" color="#FF9529" />
                    <FontAwesomeIcon icon={starRegular} size="lg" color="#FF9529" />
                    <FontAwesomeIcon icon={starRegular} size="lg" color="#FF9529" />
                </div>

                {!imageLikeState && (
                    <FontAwesomeIcon
                        onClick={() => like(image.public_id, TAGS.FAV)}
                        icon={liked ? heartSolid : heartOutline}
                        size="lg"
                        color="#1A8CC9"
                    />
                )}

                {imageLikeState && <img className="spinner" src={Spinner} alt="Loading Spinner" />}
            </div>
        </div>
    );
}
const imageLikeState = useSelector(likeImagePending);
const imageDeleteState = useSelector(deleteImagePending);

基于此,您似乎有一个选择器可以告诉您是否有 任何 个图像待处理。您想要的是一个选择器,它会告诉您 特定的 图片 ID 是否待处理。

组件代码应该如下所示

const imageLikeState = useSelector(likeImagePending(image.public_id));
const imageDeleteState = useSelector(deleteImagePending(image.public_id));

这意味着您需要更改选择器,可能还需要更改 redux 状态。如果您当前正在存储 isLikePendingboolean 值,一个简单的解决方案是更改它,以便存储在您的 redux 状态中的值是待定图像的数字 ID,或者 false 如果 none 待处理。

您的选择器将检查您在参数中传递的 ID 是否与待定 ID 和 return 匹配 boolean.

const isLikePending = (id) => (state) => {
   return state.isLikePending === id;
}