如何在订阅操作后触发useIsUserSubscribed自定义hook重新渲染
这个需求完全可以实现,以下是两种常用的落地方式:
方案1:给自定义hook新增手动刷新方法,操作后触发重新校验
你原来的useIsUserSubscribed hook只会在publisherId和currentUserId变化时才重新调用接口校验订阅状态,订阅/取消订阅操作不会触发这两个参数变化,所以不会自动刷新。我们可以给hook新增一个刷新触发标识,对外暴露刷新方法:
改后的useIsUserSubscribed代码:
import { useState, useEffect } from "react"; import { useSelector } from "react-redux"; import { checkSubscription } from "../services"; // 入参、返回值调整:返回[订阅状态, 手动刷新方法] function useIsUserSubscribed(publisherId) { const [userIsSubscribed, setUserIsSubscribed] = useState(null); // 新增刷新标识,用于手动触发useEffect执行 const [refreshFlag, setRefreshFlag] = useState(0); const currentUserId = useSelector((state) => state.auth.user?.id); useEffect(() => { if (!currentUserId || !publisherId) return; async function fetchCheckSubscriptionData() { try { await checkSubscription(publisherId); setUserIsSubscribed(true); } catch (err) { setUserIsSubscribed(false); } } fetchCheckSubscriptionData(); // 依赖项新增refreshFlag,每次refreshFlag变化就会重新执行校验 }, [publisherId, currentUserId, refreshFlag]); // 返回状态和手动刷新方法 return [ userIsSubscribed, // 刷新方法:修改refreshFlag触发useEffect重跑 () => setRefreshFlag(prev => prev + 1) ]; } export default useIsUserSubscribed;
改后的按钮组件代码:
import React from "react"; // 注意你原来的代码里导入的是add、remove方法,调用时却用了addSubscription、removeSubscription,这里同步修正 import { add as addSubscription, remove as removeSubscription } from "../../services"; import useIsUserSubscribed from "../../hooks/useIsUserSubscribed"; const SubscribeUnsubscribeBtn = ({profilePageUserId}) => { // 拿到订阅状态和刷新方法 const [userIsSubscribed, refetchSubscriptionStatus] = useIsUserSubscribed(profilePageUserId); const onClick = async () => { if (userIsSubscribed) { await removeSubscription(profilePageUserId); } else { await addSubscription(profilePageUserId); } // 调用刷新方法,触发hook重新校验订阅状态 refetchSubscriptionStatus(); } return ( <button type="button" className="sub-edit-unsub-btn bsc-button" onClick={onClick}> {userIsSubscribed ? '已订阅' : '未订阅'} </button> ); } export default SubscribeUnsubscribeBtn;
方案2:乐观更新(更推荐,体验更流畅)
如果你的订阅/取消订阅接口成功率很高,可以不用重新调用校验接口,操作完成后直接本地修改订阅状态,响应速度更快:
改后的useIsUserSubscribed代码:
import { useState, useEffect } from "react"; import { useSelector } from "react-redux"; import { checkSubscription } from "../services"; function useIsUserSubscribed(publisherId) { const [userIsSubscribed, setUserIsSubscribed] = useState(null); const currentUserId = useSelector((state) => state.auth.user?.id); useEffect(() => { if (!currentUserId || !publisherId) return; async function fetchCheckSubscriptionData() { try { await checkSubscription(publisherId); setUserIsSubscribed(true); } catch (err) { setUserIsSubscribed(false); } } fetchCheckSubscriptionData(); }, [publisherId, currentUserId]); // 返回状态和直接修改状态的方法 return [userIsSubscribed, setUserIsSubscribed]; } export default useIsUserSubscribed;
改后的按钮组件代码:
import React from "react"; import { add as addSubscription, remove as removeSubscription } from "../../services"; import useIsUserSubscribed from "../../hooks/useIsUserSubscribed"; const SubscribeUnsubscribeBtn = ({profilePageUserId}) => { const [userIsSubscribed, setUserIsSubscribed] = useIsUserSubscribed(profilePageUserId); const onClick = async () => { // 可自行添加loading状态避免重复点击,这里省略实现 if (userIsSubscribed) { await removeSubscription(profilePageUserId); // 取消成功直接本地设为false setUserIsSubscribed(false); } else { await addSubscription(profilePageUserId); // 订阅成功直接本地设为true setUserIsSubscribed(true); } } return ( <button type="button" className="sub-edit-unsub-btn bsc-button" onClick={onClick}> {userIsSubscribed ? '已订阅' : '未订阅'} </button> ); } export default SubscribeUnsubscribeBtn;
内容的提问来源于stack exchange,提问作者Simone Anthony
相关产品推荐
相关产品推荐

