2025-07-23 17:28:36 +08:00

179 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: React
date: 2025-07-23 15:56:46
tags:
---
# 父子组件传递事件
## 子组件是模态框确定按钮需要增加loading状态
### **子组件:增加 `confirmLoading` 状态并优化 `handleOk` 方法**
```tsx
import React, { useState } from 'react';
import { Modal, Checkbox, Input, message } from 'antd';
import { useTranslation } from 'react-i18next'
const { TextArea } = Input;
interface FeedbackModalProps {
open: boolean;
onOk: (selectedOption: number | null, feedbackText: string) => Promise<void>;
onCancel: () => void;
}
const FeedbackModal: React.FC<FeedbackModalProps> = ({ open, onOk, onCancel }) => {
const [selectedOption, setSelectedOption] = useState<number | null>(null);
const [feedbackText, setFeedbackText] = useState<string>('');
const { t } = useTranslation()
const [confirmLoading, setConfirmLoading] = useState(false);
const handleOk = async () => {
if (!feedbackText) {
message.warning('请填写反馈建议');
return;
}
setConfirmLoading(true)
try {
await onOk(selectedOption, feedbackText);
} finally {
setConfirmLoading(false)
}
};
return (
<Modal
title="反馈"
open={open}
onOk={handleOk}
onCancel={onCancel}
okText={`${t('common.operation.confirm')}`}
cancelText={`${t('common.operation.cancel')}`}
confirmLoading={confirmLoading}
>
{/* <div>
<Checkbox
checked={selectedOption === 0}
onChange={() => setSelectedOption(0)}
>
新增
</Checkbox>
<Checkbox
checked={selectedOption === 1}
onChange={() => setSelectedOption(1)}
>
修改
</Checkbox>
</div> */}
<TextArea
rows={4}
placeholder="请输入您的反馈建议"
value={feedbackText}
onChange={(e) => setFeedbackText(e.target.value)}
/>
</Modal>
);
};
export default FeedbackModal;
```
### **父组件:确保 `handleFeedbackSubmit` 返回 Promise**
```tsx
const handleFeedbackSubmit = useCallback(
async (selectedOption: number | null, feedbackText: string) => {
console.log(currentMessageId);
console.log(currentFeedback);
try {
// 构造请求参数
const requestBody = {
operationType: currentFeedback!.rating, // 0 或 1
feedbackText, // 用户反馈建议
conversationId: currentConversationId, // 会话 ID
messageId: currentMessageId, // 消息 ID
username: getCookieValue('username'), // 用户名
};
// 调用 Java 接口
const javaResponse = await fetch(
`/dev-api/api/conversation/feedback`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(requestBody),
}
);
// 调用原有的 updateFeedback 函数
await updateFeedback(
{
url: `/messages/${currentMessageId}/feedbacks`,
body: { rating: currentFeedback!.rating },
},
// isInstalledApp,
// appId
);
// 显示成功通知
notify({ type: "success", message: t("common.api.success") });
if (resolveFeedback) {
resolveFeedback(true); // 用户取消了反馈
setResolveFeedback(null);
}
// 关闭对话框
setIsFeedbackModalVisible(false);
} catch (error) {
console.error("Error:", error);
notify({ type: "error", message: t("common.api.failed") });
} finally {
setIsSubmittingNow(false);
}
},
[
currentMessageId,
currentFeedback,
currentConversationId,
isInstalledApp,
appId,
notify,
t,
]
);
```
父组件调用子组件部分
```tsx
<FeedbackModal
open={isFeedbackModalVisible}
onOk={handleFeedbackSubmit}
onCancel={() => {
if (resolveFeedback) {
resolveFeedback(false); // 用户取消了反馈
setResolveFeedback(null);
}
setIsFeedbackModalVisible(false)
}}
/>
```
### **关键点说明**
1. **子组件内部管理加载状态**
通过 `useState` 创建 `isLoading` 状态,并在 `handleOk` 中控制其值。点击按钮时,`isLoading` 变为 `true`,请求结束后变为 `false`
2. **`okButtonProps` 绑定加载状态**
Ant Design 的 `Modal` 组件支持通过 `okButtonProps` 自定义按钮属性,这里将 `loading` 绑定到 `isLoading` 状态。
3. **`onOk` 作为异步函数传递**
父组件的 `handleFeedbackSubmit``async` 函数,返回 Promise。子组件通过 `await onOk()` 确保加载状态在请求结束后更新。
4. **错误处理不影响加载状态**
使用 `try...finally` 确保无论请求成功或失败,`isLoading` 都会被重置。