使用 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 状态。如果您当前正在存储 isLikePending
的 boolean
值,一个简单的解决方案是更改它,以便存储在您的 redux 状态中的值是待定图像的数字 ID,或者 false
如果 none 待处理。
您的选择器将检查您在参数中传递的 ID 是否与待定 ID 和 return 匹配 boolean
.
const isLikePending = (id) => (state) => {
return state.isLikePending === id;
}
我有一个加载图像的应用程序,我想单击 '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 状态。如果您当前正在存储 isLikePending
的 boolean
值,一个简单的解决方案是更改它,以便存储在您的 redux 状态中的值是待定图像的数字 ID,或者 false
如果 none 待处理。
您的选择器将检查您在参数中传递的 ID 是否与待定 ID 和 return 匹配 boolean
.
const isLikePending = (id) => (state) => {
return state.isLikePending === id;
}