179 lines
4.9 KiB
Markdown
179 lines
4.9 KiB
Markdown
---
|
||
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` 都会被重置。
|