fix(stock): 매매알람 detail 객체 렌더 크래시(React #31) 방지

/api/stock/trade-alerts의 alerts[].detail은 condition별 가변 객체
({ma50,ma200,severity} 등)인데 JSX 자식으로 직접 렌더 → React #31로
페이지 크래시(워커가 실제 알람 발화 시작하며 발현, BE msg #17).

formatDetail 헬퍼 추가: 객체를 안전 문자열로 변환(알려진 키 한글 라벨,
*_pct 퍼센트, null 값 스킵, 미정의 키도 원문 폴백 — 스키마 가정 없음).
AlertCard가 detail 대신 formatDetail(detail) 렌더.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UHXzpsZQxKG9hQmNRfZjRS
This commit is contained in:
2026-07-03 22:06:11 +09:00
parent 970c8164e0
commit d57f9b9b65
4 changed files with 81 additions and 3 deletions

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import Loading from '../../../components/Loading';
import { kindMeta, conditionLabel, relativeTime } from '../watchlistUtils';
import { kindMeta, conditionLabel, relativeTime, formatDetail } from '../watchlistUtils';
import { formatNumber } from '../stockUtils';
const DAYS_OPTIONS = [
@@ -11,6 +11,7 @@ const DAYS_OPTIONS = [
const AlertCard = ({ a }) => {
const meta = kindMeta(a.kind);
const detailText = formatDetail(a.detail);
return (
<div className="wl-alert">
<div className="wl-alert__head">
@@ -23,7 +24,7 @@ const AlertCard = ({ a }) => {
<span className="wl-cond">{conditionLabel(a.condition)}</span>
{a.price != null && <span className="wl-alert__price">{formatNumber(a.price)}</span>}
</div>
{a.detail && <div className="wl-alert__detail">{a.detail}</div>}
{detailText && <div className="wl-alert__detail">{detailText}</div>}
</div>
);
};