最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2023年06月29日 09:47:15   作者:hahayq  
這篇文章主要給大家詳細(xì)介紹如何用React實(shí)現(xiàn)一個類 chatGPT 的交互式問答組件的方法,文中有詳細(xì)的代碼示例,對我們學(xué)習(xí)有一定的幫助,需要的朋友可以參考下

API文檔

屬性名描述類型默認(rèn)值
recommendList推薦模板列表string[] | undefinednull
commonUseList常用模板列表string[] | undefinednull
uploadProps文件上傳,同 antd Upload 組件{ accept?: string; children?: ReactNode; maxCount?: number; multiple?: boolean; } | undefinednull
autoCompleteProps輸入框自動補(bǔ)全,同 antd AutoComplete 組件{ options?: DefaultOptionType[]; onSearch?: ((value: string) => void); } | undefinednull
onSend發(fā)送消息((msg: IQuestion) => void) | undefinednull
onMsgLike點(diǎn)贊回答((msg: IQuestion) => void) | undefinednull
onMsgNotLike點(diǎn)踩回答((msg: IQuestion) => void) | undefinednull
onRefresh刷新回答((msg: IQuestion) => void) | undefinednull
renderAvatar自定義頭像((msg: IMessage) => ReactNode) | undefinednull
renderTools自定義消息框底部操作欄((msg: IMessage) => ReactNode) | undefinednull
isAnimation是否開啟消息動畫效果boolean | undefinednull
className自定義類名boolean | undefinednull
style自定義樣式CSSProperties | undefinednull
loading加載狀態(tài)boolean | undefinednull
messages消息列表IMessage[] | undefinednull
# 功能介紹
這個組件的主要功能主要包括:
  • 輸入框上傳附件
  • 輸入框自動補(bǔ)全
  • 自定義消息操作欄
  • 自定義頭像
  • 模板調(diào)用

下面會挨個介紹功能

輸入框上傳文件

這個功能很簡單就是支持輸入框上傳附件,然后會把附件和問題一起丟給使用者,由使用者自己去調(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![lena](https://img1.baidu.com/it/u=2041864569,220923158&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=284)'
          });
        }, 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)容改變時去請求關(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![lena](https://img1.baidu.com/it/u=2041864569,220923158&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=284)'
          });
        }, 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![lena](https://img1.baidu.com/it/u=2041864569,220923158&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=284)',
            renderTools: (msg: IMessage) => <div>點(diǎn)個贊吧</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這個方法,通過傳入的消息類型來判斷顯示那個頭像,效果如下

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)用

這個功能是比賽要求的,需要給用戶提供一些模板,用戶點(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)用這個hook可以獲取到messages、onRefresh、onSend、loading這幾個主要的props,其他的props你也可以自己傳入. 這個自定義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這個hook,傳入api接口(需要返回promise)就可以了,至于其他的組件api也可以一并傳入,還支持傳入歷史消息列表.然后這個hook就會返回所有該組件所需要的props,包括消息發(fā)送方法,消息刷新方法,組件loading狀態(tài),消息列表等.是不是很方便呢,哈哈.

以上就是用React實(shí)現(xiàn)一個類 chatGPT 的交互式問答組件的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于React chatGPT問答組件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React自定義hook的方法

    React自定義hook的方法

    Hook是 React 16.8 的新增特性。它通常與函數(shù)式組件同時使用。可以使函數(shù)式組件在不編寫 class 的情況下,可以擁有class組件的狀態(tài)、生命周期、引用等功能,這篇文章主要介紹了React自定義hook的相關(guān)知識,需要的朋友可以參考下
    2022-06-06
  • React中Portals與錯誤邊界處理實(shí)現(xiàn)

    React中Portals與錯誤邊界處理實(shí)現(xiàn)

    本文主要介紹了React中Portals與錯誤邊界處理實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • 一文詳解React類組件中的refs屬性

    一文詳解React類組件中的refs屬性

    react中的ref類似于vue中的ref,都是可以操作dom的,這篇文章我們通過一個demo來學(xué)習(xí)這個屬性,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下
    2023-08-08
  • React?SSR架構(gòu)Stream?Rendering與Suspense?for?Data?Fetching

    React?SSR架構(gòu)Stream?Rendering與Suspense?for?Data?Fetching

    這篇文章主要為大家介紹了React?SSR架構(gòu)Stream?Rendering與Suspense?for?Data?Fetching解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Parcel 打包示例(React HelloWorld)

    Parcel 打包示例(React HelloWorld)

    本篇文章主要介紹了Parcel 打包示例(React HelloWorld),詳細(xì)的介紹了Parcel打包的特點(diǎn)和使用示例,有興趣的可以了解一下
    2018-01-01
  • react hooks實(shí)現(xiàn)原理解析

    react hooks實(shí)現(xiàn)原理解析

    這篇文章主要介紹了react hooks實(shí)現(xiàn)原理,文中給大家介紹了useState dispatch 函數(shù)如何與其使用的 Function Component 進(jìn)行綁定,節(jié)后實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • 詳解超簡單的react服務(wù)器渲染(ssr)入坑指南

    詳解超簡單的react服務(wù)器渲染(ssr)入坑指南

    這篇文章主要介紹了詳解超簡單的react服務(wù)器渲染(ssr)入坑指南,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02
  • React中CSS模塊沖突的問題及解決

    React中CSS模塊沖突的問題及解決

    本文將探討 React 中 CSS 模塊沖突的常見原因,并提供解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 深入理解React?State?原理

    深入理解React?State?原理

    本文主要介紹了React?State?原理,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • react render的原理及觸發(fā)時機(jī)說明

    react render的原理及觸發(fā)時機(jī)說明

    這篇文章主要介紹了react render的原理及觸發(fā)時機(jī)說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論

文化| 凭祥市| 横山县| 千阳县| 上饶市| 昌都县| 墨竹工卡县| 澄城县| 泰兴市| 绥中县| 正定县| 历史| 岚皋县| 洪雅县| 吴川市| 什邡市| 梅州市| 资兴市| 苏州市| 和平区| 呈贡县| 东方市| 章丘市| 马鞍山市| 新津县| 萍乡市| 平山县| 稻城县| 吉首市| 五常市| 竹北市| 全椒县| 乌拉特中旗| 遵化市| 田阳县| 海淀区| 紫金县| 高邑县| 乐安县| 大兴区| 托克托县|