You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在点击订阅按钮后触发自定义hook useIsUserSubscribed重新渲染更新

这个需求完全可以实现,不需要推翻现有逻辑,下面是两种常用的实现方案:

方案1:改造自定义hook,暴露刷新方法(最推荐)

修改useIsUserSubscribed,将内部的订阅状态查询逻辑抽离并暴露给调用方,点击按钮调用完订阅接口后手动触发查询即可:

改造后的hook代码

import { useState, useEffect, useCallback } 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);

  // 抽离查询逻辑,用useCallback包裹避免不必要的重生成
  const fetchSubscriptionStatus = useCallback(async () => {
    if (!currentUserId || !publisherId) return;
    try {
      await checkSubscription(publisherId);
      setUserIsSubscribed(true);
    } catch (err) {
      setUserIsSubscribed(false);
    }
  }, [publisherId, currentUserId]);

  useEffect(() => {
    fetchSubscriptionStatus();
  }, [fetchSubscriptionStatus]);

  // 同时返回状态和刷新方法
  return [userIsSubscribed, fetchSubscriptionStatus];
}

export default useIsUserSubscribed;

改造后的按钮组件代码

import React from "react";
// 注意原代码导入的add、remove和实际调用的addSubscription、removeSubscription不一致,属于笔误请自行修正
import { addSubscription, 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);
    }
    // 调用刷新方法重新拉取最新的订阅状态
    await refetchSubscriptionStatus();
  }

  // 可选:状态为null时展示加载态,避免请求过程中用户重复点击
  if (userIsSubscribed === null) {
    return <button type="button" className="sub-edit-unsub-btn bsc-button" disabled>加载中</button>
  }

  return (
    <button type="button" className="sub-edit-unsub-btn bsc-button" onClick={onClick}>
          {userIsSubscribed ? 'Subscribed' : 'Unsubscribed'}
    </button>
  );
} 

方案2:乐观更新(体验更流畅)

如果不需要严格和后端实时对齐,可以直接在本地修改状态,减少一次额外的查询接口请求,用户点击后页面会立刻发生变化:

改造后的hook代码

import { useState, useEffect, useCallback } 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);

  const fetchSubscriptionStatus = useCallback(async () => {
    if (!currentUserId || !publisherId) return;
    try {
      await checkSubscription(publisherId);
      setUserIsSubscribed(true);
    } catch (err) {
      setUserIsSubscribed(false);
    }
  }, [publisherId, currentUserId]);

  useEffect(() => {
    fetchSubscriptionStatus();
  }, [fetchSubscriptionStatus]);

  // 额外返回状态更新方法,允许外部手动修改状态
  return [userIsSubscribed, fetchSubscriptionStatus, setUserIsSubscribed];
}

改造后的点击逻辑

const onClick = async () => {
  // 先乐观更新状态,页面立刻响应
  const newStatus = !userIsSubscribed;
  setUserIsSubscribed(newStatus);
  try {
    if (userIsSubscribed) {
      await removeSubscription(profilePageUserId);
    } else {
      await addSubscription(profilePageUserId);
    }
  } catch (err) {
    // 接口调用失败时回滚状态
    setUserIsSubscribed(!newStatus);
  }
}

不推荐的临时方案:如果不想修改hook,可以给按钮组件绑定一个数字类型的key,点击后将key+1触发组件重新挂载,但是会重走所有生命周期,性能较差,仅适合临时调试使用。

内容的提问来源于stack exchange,提问作者Simone Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 07:06:04