用React實(shí)現(xiàn)一個(gè)類 chatGPT 的交互式問答組件的方法詳解

API文檔
| 屬性名 | 描述 | 類型 | 默認(rèn)值 |
|---|---|---|---|
| recommendList | 推薦模板列表 | string[] | undefined | null |
| commonUseList | 常用模板列表 | string[] | undefined | null |
| uploadProps | 文件上傳,同 antd Upload 組件 | { accept?: string; children?: ReactNode; maxCount?: number; multiple?: boolean; } | undefined | null |
| autoCompleteProps | 輸入框自動補(bǔ)全,同 antd AutoComplete 組件 | { options?: DefaultOptionType[]; onSearch?: ((value: string) => void); } | undefined | null |
| onSend | 發(fā)送消息 | ((msg: IQuestion) => void) | undefined | null |
| onMsgLike | 點(diǎn)贊回答 | ((msg: IQuestion) => void) | undefined | null |
| onMsgNotLike | 點(diǎn)踩回答 | ((msg: IQuestion) => void) | undefined | null |
| onRefresh | 刷新回答 | ((msg: IQuestion) => void) | undefined | null |
| renderAvatar | 自定義頭像 | ((msg: IMessage) => ReactNode) | undefined | null |
| renderTools | 自定義消息框底部操作欄 | ((msg: IMessage) => ReactNode) | undefined | null |
| isAnimation | 是否開啟消息動畫效果 | boolean | undefined | null |
| className | 自定義類名 | boolean | undefined | null |
| style | 自定義樣式 | CSSProperties | undefined | null |
| loading | 加載狀態(tài) | boolean | undefined | null |
| messages | 消息列表 | IMessage[] | undefined | null |
| # 功能介紹 | |||
| 這個(gè)組件的主要功能主要包括: |
- 輸入框上傳附件
- 輸入框自動補(bǔ)全
- 自定義消息操作欄
- 自定義頭像
- 模板調(diào)用
下面會挨個(gè)介紹功能
輸入框上傳文件
這個(gè)功能很簡單就是支持輸入框上傳附件,然后會把附件和問題一起丟給使用者,由使用者自己去調(diào)用api接口來獲取回答.上傳組件采用的是antd的Upload組件,API也一致.大致代碼如下:
import React from 'react';
import { Chat, useMessage, EMessageType } from './chat';
export default function () {
const { msgProps } = useMessage(
(question, lastAnswer) => {
return new Promise((resolve, reject) => {
const { content, fileList } = question;
setTimeout(() => {
resolve({
content:
'\n\n' +
(lastAnswer ? '## 我又想了一下 \n\n' : '') +
content?.replace(/嗎/g, '呢').replace(/你/g, '我') +
'\n\n' +
fileList.map((item) => item.name).join(' ') +
'\n\n'
});
}, 2000);
});
},
{
uploadProps: {
multiple: true
},
defaultMsgs: [
{
key: 1,
type: EMessageType.AI,
content: '快來和我對話吧',
renderTools: () => null,
isAnimation: false
}
]
}
);
return (
<Chat {...msgProps} />
);
}輸入框自動補(bǔ)全
自動補(bǔ)全采用的是antd的Autocomplete組件,API也一致,原理就是當(dāng)輸入框內(nèi)容改變時(shí)去請求關(guān)聯(lián)內(nèi)容然后改變Autocomplete的options,就能實(shí)現(xiàn)自動補(bǔ)全啦.
import React, { useState } from 'react';
import { Chat, useMessage, EMessageType, IMessage } from './chat';
export default function () {
const [options, setOptions] = useState<{ value: string }[]>([]);
const handleSearch = (value: string) => {
setOptions(!value ? [] : [{ value }, { value: value + value }, { value: value + value + value }]);
};
const { msgProps } = useMessage(
(question, lastAnswer) => {
return new Promise((resolve, reject) => {
const { content } = question;
setTimeout(() => {
resolve({
isAnimation: !!lastAnswer,
content:
'\n\n' +
(lastAnswer ? '## 我又想了一下 \n\n' : '') +
content?.replace(/嗎/g, '呢').replace(/你/g, '我') +
'\n\n'
});
}, 2000);
});
},
{
autoCompleteProps: {
options,
onSearch: handleSearch
}
}
);
return (
<Chat {...msgProps} />
);
}自定義消息操作欄
由于每條消息下方還有操作欄,默認(rèn)的有重新回答、點(diǎn)贊、點(diǎn)踩、復(fù)制等,所以提供了自定義的功能,如果不需要默認(rèn)的這些功能也可以關(guān)閉或者自定義.

import React from 'react';
import { Chat, useMessage, EMessageType, IMessage } from './chat';
export default function () {
const { msgProps } = useMessage(
(question, lastAnswer) => {
return new Promise((resolve, reject) => {
const { content } = question;
setTimeout(() => {
resolve({
content:
'\n\n' +
(lastAnswer ? '## 我又想了一下 \n\n' : '') +
content?.replace(/嗎/g, '呢').replace(/你/g, '我') +
'\n\n',
renderTools: (msg: IMessage) => <div>點(diǎn)個(gè)贊吧</div>
});
}, 2000);
});
},
{
renderTools: (msg: IMessage) => <div>這里是自定義操作欄</div>,
defaultMsgs: [
{
key: 1,
type: EMessageType.AI,
content: '快來和我對話吧',
renderTools: () => null,
isAnimation: false
},
{
key: 2,
type: EMessageType.AI,
content: '支持每條消息獨(dú)立設(shè)置操作欄',
renderTools: (msg: IMessage) => <div>這里是消息獨(dú)立操作欄</div>,
isAnimation: false
}
]
}
);
return (
<BixiProvider locale={enUS}>
<Chat {...msgProps} />
</BixiProvider>
);
}自定義頭像
既然是對話,那肯定得提供自定義頭像的功能啦,使用方式的話是傳入renderAvatar這個(gè)方法,通過傳入的消息類型來判斷顯示那個(gè)頭像,效果如下

import React from 'react';
import { Chat, useMessage, EMessageType, IMessage } from './chat';
export default function () {
const { msgProps } = useMessage(
(question, lastAnswer) => {
return new Promise((resolve, reject) => {
const { content } = question;
setTimeout(() => {
resolve({
content:
'\n\n' +
(lastAnswer ? '## 我又想了一下 \n\n' : '') +
content?.replace(/嗎/g, '呢').replace(/你/g, '我')
});
}, 2000);
});
},
{
renderAvatar: (msg: IMessage) => <>{msg.type === EMessageType.AI ? '人工智障' : '大帥比'}</>,
defaultMsgs: [
{
key: 1,
type: EMessageType.AI,
content: '快來和我對話吧',
renderTools: () => null,
isAnimation: false
},
{
key: 2,
type: EMessageType.Self,
content: '你真的是人工智能嗎',
isAnimation: false
},
{
key: 3,
type: EMessageType.AI,
content: '支持每條消息單獨(dú)設(shè)置頭像',
isAnimation: false
}
]
}
);
return (
<Chat {...msgProps} />
);
}模板調(diào)用
這個(gè)功能是比賽要求的,需要給用戶提供一些模板,用戶點(diǎn)擊模板就可以快速搜索答案之類的,在輸入框輸入“/”就可以喚醒模板了,實(shí)現(xiàn)方式也很簡單,監(jiān)聽輸入框值的改變,如果輸入值和“/”匹配就直接喚起模板就可以了.效果如下

import React from 'react';
import { Chat, useMessage, EMessageType, IMessage } from './chat';
export default function () {
const { msgProps } = useMessage(
(question, lastAnswer) => {
return new Promise((resolve, reject) => {
const { content } = question;
setTimeout(() => {
resolve({
content:
'\n\n' +
(lastAnswer ? '## 我又想了一下 \n\n' : '') +
content?.replace(/嗎/g, '呢').replace(/你/g, '我')
});
}, 2000);
});
},
{
recommendList: ['標(biāo)題生成', '文章續(xù)寫', '文章潤色', '文章大綱', '朋友圈文案', '活動方案', '翻譯', '演講稿'],
commonUseList: ['標(biāo)題生成', '朋友圈文案'],
}
);
return (
<Chat {...msgProps} />
);
}自定義hook
除了上面的功能外,還對邏輯進(jìn)行了封裝,調(diào)用這個(gè)hook可以獲取到messages、onRefresh、onSend、loading這幾個(gè)主要的props,其他的props你也可以自己傳入. 這個(gè)自定義hook封裝了消息發(fā)送方法,消息刷新方法,組件loading狀態(tài),消息列表等主要邏輯.重新回答的原理是去消息列表中尋找之前最近的一條問題,然后在此調(diào)用獲取回答的接口 代碼如下:
import { useState, useCallback } from 'react';
import { IMessage, IChatProps, EMessageType, IQuestion } from './model';
import { uniqueId } from 'lodash-es';
type IUseMessageOption = Omit<IChatProps, 'onSend' | 'onRefresh' | 'loading' | 'messages'> & {
defaultMsgs: IMessage[];
};
type IService = (msg: IQuestion, lastAnswer?: IMessage) => Promise<IMessage>;
export function useMessage(
getMsg: IService,
{ defaultMsgs, ...props }: IUseMessageOption
): {
msgProps: IChatProps;
} {
const [messageList, setMessageList] = useState<IMessage[]>(defaultMsgs || []);
const [loading, setLoading] = useState(false);
const onRefresh = useCallback(
(item: IMessage) => {
const index = messageList.findIndex((msg) => msg.key === item.key);
if (index < 1) return;
const lastQuestion = messageList
.slice(0, index)
.reverse()
.find((msg) => msg.type === EMessageType.Self);
if (!lastQuestion) return;
setLoading(true);
getMsg(lastQuestion, messageList[index]).then((res) => {
setLoading(false);
const key = `${EMessageType.AI}-${uniqueId()}`;
messageList[index] = { ...res, key, type: EMessageType.AI };
setMessageList([...messageList]);
});
},
[getMsg, messageList]
);
const onSend = useCallback(
(msg: IQuestion) => {
setLoading(true);
setMessageList((list) => list.concat({ ...msg, key: `${EMessageType.Self}-${uniqueId()}`, type: EMessageType.Self }));
getMsg(msg).then((res) => {
setLoading(false);
const key = `${EMessageType.AI}-${uniqueId()}`;
setMessageList((list) => list.concat({ ...res, key, type: EMessageType.AI }));
});
},
[getMsg]
);
return {
msgProps: {
messages: messageList,
onRefresh,
onSend,
loading,
...props
}
};
}使用方法
該組件使用起來很簡單,調(diào)用useMessage這個(gè)hook,傳入api接口(需要返回promise)就可以了,至于其他的組件api也可以一并傳入,還支持傳入歷史消息列表.然后這個(gè)hook就會返回所有該組件所需要的props,包括消息發(fā)送方法,消息刷新方法,組件loading狀態(tài),消息列表等.是不是很方便呢,哈哈.
以上就是用React實(shí)現(xiàn)一個(gè)類 chatGPT 的交互式問答組件的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于React chatGPT問答組件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React Native自定義Android的SSL證書鏈校驗(yàn)
這篇文章主要為大家介紹了React Native自定義Android的SSL證書鏈校驗(yàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
React實(shí)現(xiàn)導(dǎo)出excel文件的操作步驟
在React項(xiàng)目的TypeScript文件中,因?yàn)樵腏avaScript或TypeScript并沒有提供直接的Excel導(dǎo)出功能,常用的Excel導(dǎo)出方法通常涉及使用第三方庫,本文介紹了React實(shí)現(xiàn)導(dǎo)出excel文件的操作步驟,需要的朋友可以參考下2024-12-12
react結(jié)合typescript?封裝組件實(shí)例詳解
這篇文章主要為大家介紹了react結(jié)合typescript?封裝組件實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04

