You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React项目中如何向HTTP客户端脚本传递URL变量

解决React组件向外部脚本传递自定义URL的问题

问题分析

你的React组件WebChatWidget能正确获取到用户自定义的serviceURL,但APIClient类中输出的URL却为undefined,核心问题有三点:

  1. APIClient构造函数逻辑错误:构造函数接收了serviceURL参数,但未使用,反而尝试访问不存在的widget对象(widget仅在React组件中可用,无法在独立的APIClient类中直接调用)。
  2. 异步脚本加载时机问题:外部脚本是异步加载的,组件中直接调用方法时,脚本可能还未加载完成,导致APIClient无法接收参数。
  3. 属性名拼写错误:构造函数中console.log("Service URL:", this.serviceURL)写错了属性名,应为this.apiUrl。

解决方案

1. 修正APIClient类的构造函数

移除错误的widget.get调用,直接使用构造函数传入的serviceURL参数,并修正日志输出的属性名:

export class APIClient {
  constructor(serviceURL) {
    // 直接使用传入的serviceURL参数
    this.apiUrl = serviceURL;
    this.apiKey = process.env.REACT_APP_OPENAI_API_KEY;
    // 修正属性名:this.apiUrl 而非 this.serviceURL
    console.log("Service URL:", this.apiUrl);
  }

  async sendMessage(message) {
    console.log('API-Key:' + this.apiKey);

    try {
      const apiBody = {
        "model": "gpt-3.5-turbo",
        "messages": [{
          "role": "user",
          "content": "Can you act like you are the Chatbot of the University" +
            "of Heilbronn aka HHN and answer the following prompt and format the message with the respect to only use 100 tokens with the API call: " + message
        }],
        "max_tokens": 100,
        "temperature": 0,
      }

      console.log(JSON.stringify(apiBody))

      const response = await fetch(this.apiUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + this.apiKey,
        },
        body: JSON.stringify(apiBody),
      });

      if (!response.ok) {
        throw new Error(`Error: ${response.status} - ${response.statusText}`);
      }

      const data = await response.json();
      return data.choices[0].message.content;
    } catch (error) {
      console.error(error);
      return 'Sorry, something went wrong.';
    }
  }
}

2. 外部脚本暴露APIClient到全局作用域

确保打包后的外部脚本将APIClient挂载到window对象上,这样React组件就能在脚本加载完成后访问到它:

// 在APIClient类所在的脚本末尾添加
window.APIClient = APIClient;

3. 修正React组件的脚本加载逻辑

使用Promise等待所有外部脚本加载完成后,再实例化APIClient并传入serviceURL,同时避免重复加载脚本:

import * as React from "react";
import * as Scrivito from "scrivito";
import "./WebChatWidget.scss";

const WebChatWidget = ({ widget }) => {
  const serviceURL = widget.get("serviceURL");
  console.log("Service URL Widget:", serviceURL);

  React.useEffect(() => { 
    // 移除已存在的脚本,防止重复加载
    const existingScripts = document.querySelectorAll(
      'script[src="/static/js/main.14ec3828.js"], script[src="/static/js/787.4ed02641.chunk.js"]'
    );
    existingScripts.forEach(script => script.remove());

    // 创建加载脚本的Promise函数
    const loadScript = (src) => {
      return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = src;
        script.async = true;
        script.onload = () => resolve();
        script.onerror = (err) => reject(err);
        document.body.appendChild(script);
      });
    };

    // 按顺序加载所有脚本,完成后实例化APIClient
    Promise.all([
      loadScript("/static/js/main.14ec3828.js"),
      loadScript("/static/js/787.4ed02641.chunk.js")
    ]).then(() => {
      if (window.APIClient) {
        // 实例化APIClient并传入自定义URL
        const apiClient = new window.APIClient(serviceURL);
        // 可将apiClient存储到组件状态或全局,供聊天逻辑使用
        console.log("APIClient initialized with URL:", serviceURL);
      } else {
        console.error("APIClient未在全局作用域中找到");
      }
    }).catch(error => {
      console.error("脚本加载失败:", error);
    });

    // 清理函数:组件卸载时移除脚本
    return () => {
      const scripts = document.querySelectorAll(
        'script[src="/static/js/main.14ec3828.js"], script[src="/static/js/787.4ed02641.chunk.js"]'
      );
      scripts.forEach(script => script.remove());
    };
  }, [serviceURL]);

  return <div id="Chatbot" className="WebChatWidget" style={{ zIndex: 1000 }}></div>;
};

Scrivito.provideComponent("WebChatWidget", WebChatWidget);

验证效果

完成上述修改后,重新运行项目:

  • React组件会在serviceURL变化时,重新加载脚本并实例化APIClient
  • APIClient构造函数中的日志会正确输出用户自定义的URL
  • 聊天功能会使用传入的自定义URL发起请求

内容的提问来源于stack exchange,提问作者bayd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 18:24:57