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

React ProfileCard星标收藏功能实现与点击事件冲突处理

React个人资料卡片星标收藏功能修改方案

核心修改点

  • 移除原评分功能相关冗余代码,仅保留星标作为收藏按钮
  • 阻止星标点击事件冒泡,避免触发卡片跳转详情的逻辑
  • 基于登录状态条件渲染星标,未登录用户完全不展示该组件

完整修改后代码

import React, {useState, useEffect} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faMapMarkerAlt} from '@fortawesome/free-solid-svg-icons';
import {ServiceType} from 'shared/models/profile/serviceType';
import {toTitleCase} from 'shared/utils/string';
import {FeeKind} from 'shared/models/fee-kind/FeeKind';
import {useAuth} from 'shared/hooks/useAuth';
import {ProfileCardFee} from 'shared/components/ProfileCard/ProfileCardFee/ProfileCardFee';
import {StarRatingStar} from 'shared/components/StarRating/StarRatingStar';
// 请替换为你实际的收藏接口引入路径
import { createFavoriteAsync } from 'src/api/favorite';
import './style.scss';
import {getFullName} from 'shared/utils/profile';
import {IProfile} from 'shared/models/profile/IProfile';

interface IProfileCardProps {
    profile: IProfile;
    onClickDetail?: () => void;
}

export const ProfileCardDetails = ({profile, onClickDetail}: IProfileCardProps) => {
    const fullName = getFullName(profile);
    const professionTitle = profile.profession ? toTitleCase(profile.profession) : null;
    // 替换原评分状态为收藏状态
    const [isFavorited, setIsFavorited] = useState<boolean>(false);
    const {isAuthenticated, tokenData} = useAuth();

    // 收藏点击逻辑
    const handleFavoriteClick = async (e: React.MouseEvent) => {
        // 阻止事件冒泡,不触发外层卡片的跳转逻辑
        e.stopPropagation();
        if (!tokenData) return;
        try {
            await createFavoriteAsync({
                user_id: tokenData.id,
                profile_id: profile.id,
            });
            // 切换收藏状态,也可根据接口返回值更新
            setIsFavorited(prev => !prev);
        } catch (err) {
            // 可按需添加收藏失败的提示逻辑
            console.error('收藏失败', err);
        }
    };

    return (
        <div onClick={onClickDetail} className="ProfileCard__details d-flex justify-content-between">
            <div>
                <div className="ProfileCard__profession">{professionTitle || 'undefined'}</div>
                <div className="ProfileCard__title">{fullName}</div>
                <div className="ProfileCard__location">
                    <FontAwesomeIcon icon={faMapMarkerAlt} className="ProfileCard__location-icon" />
                    {profile?.contact_details_display?.city}
                </div>
            </div>
            <div className="flex_colum_end">
                {/* 仅登录用户展示收藏星标 */}
                {isAuthenticated ? (
                    <div className="text_align_end ProfileCard__star_icon">
                        <StarRatingStar
                            isClickable={true}
                            onClick={handleFavoriteClick}
                            isActive={isFavorited}
                            // 移除原评分需要的hover相关逻辑,不需要可直接删除对应属性
                            onMouseEnter={() => {}}
                            onMouseLeave={() => {}}
                            isHover={false}
                        />
                    </div>
                ) : null}
                <div
                    className={
                        profile && profile.service_types && profile.service_types.includes('FIXED_FEES' as ServiceType)
                            ? 'flex_row_center mobileDayHour Hourly_rate_responsive'
                            : 'flex_center'
                    }
                >
                    <div
                        className={
                            profile &&
                            profile.service_types &&
                            profile.service_types.includes('FIXED_FEES' as ServiceType)
                                ? 'text_align_end'
                                : 'text_align_end'
                        }
                    >
                        <ProfileCardFee amount={profile.service_details?.hour_rate as number} kind={FeeKind.Hour} />
                    </div>
                    <div className="text_align_end pl-3">
                        <ProfileCardFee amount={profile.service_details?.day_rate as number} kind={FeeKind.Day} />
                    </div>
                </div>

                <div className="fixed_fee_enum_div">
                    {profile &&
                        profile.service_types &&
                        profile.service_types.includes('FIXED_FEES' as ServiceType) && (
                            <>
                                <div className="fixed_fee_enum_svg">
                                    <img
                                        className="fixed_fee_enum_svg_icon"
                                        src="/assets/profileIcons/lock.svg"
                                        alt="Rightful Logo"
                                    />
                                </div>
                                <div className="fixed_fee_enum_text">Fixed Fee Options</div>
                            </>
                        )}
                </div>
            </div>
        </div>
    );
};

补充说明

如果需要初始化星标的选中状态,可以在组件挂载时调用查询接口,判断当前用户是否已经收藏该资料,更新isFavorited的初始值即可。如果需要支持取消收藏功能,也可以在handleFavoriteClick里判断当前状态,调用对应的取消收藏接口即可。

内容的提问来源于stack exchange,提问作者Chris Dobbs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:48:00