在更改时更新 TradingView 热门列表小部件

Update TradingView Hotlist Widget onChange

下面是我用于启动小部件的组件,我想在从 select 标记 select 编辑新值时更改交换。 onChange 更改状态值,但是小部件不会更改它正在查看的值。有什么想法可以让它发挥作用吗?

import React from "react"; 

export default  class StockGainer extends React.PureComponent {
    constructor(props) {
        super(props);
        this._ref = React.createRef();
        this.state = { 
        exchange:
         "TSX" 
        }
    }
 componentDidMount() {
        const script = document.createElement('script');
        script.src = 'https://s3.tradingview.com/external-embedding/embed-widget-hotlists.js' 
        script.async = true;
        this._ref.current.appendChild(script);
        script.innerHTML = JSON.stringify(
            {
                  "colorTheme": "dark",
                  "dateRange": "12M",
                  "exchange": `${this.state.exchange}`,
                  "showChart": true,
                  "locale": "en"
                })
    }
   


    render() {

        const Changeexchange = (e) => { 

            this.setState({exchange: e.target.value})
        }  

        const SelectBox = () => (
            <div class="select-div">
            <select className="exchange" value={this.state.exchange} name="pagination" onChange={Changeexchange}>
              <option value="US"> USA (US Exchanges)</option>
              <option value="NASDAQ"> USA (NASDAQ)</option>
              <option value="NYSE"> USA (NYSE)</option>
              <option value="AMEX"> USA (NYSE ARCA)</option>
              <option value="OTC"> USA (OTC)  </option>
            </select>
            </div>
        )

        return(
          
        <div class="tradingview-widget-container" ref={this._ref}>
            <div style={{position:"absolute", top: "0px", left:"318px"}}>{SelectBox()}</div> 
         <div class="tradingview-widget-container__widget"> </div>
          {console.log(this.state.exchange)}
        </div>
        );
    }
   
}

改变状态下的交换是不够的,如果你想更新小部件,你需要重新创建整个脚本标签。您可以创建函数“updateWidget”并在 componentDidMount 和 changeExhange 函数中调用它。

我还为小部件 tradingView 创建了新的 div,每次更新小部件时我们都需要用 innerHTML='' 清除它。否则每次我们更改交换时它都会创建多个小部件。

import React from "react"; 

export default  class StockGainer extends React.PureComponent {
  constructor(props) {
      super(props);
      this._ref = React.createRef();
      this.state = { 
      exchange:
       "TSX" 
      }
  }
componentDidMount() {
    this.updateWidget()
  }
 
  updateWidget(){
      this._ref.current.innerHTML=''
      const script = document.createElement('script');
      script.src = 'https://s3.tradingview.com/external-embedding/embed-widget-hotlists.js' 
      script.async = true;
      this._ref.current.appendChild(script);
      script.innerHTML = JSON.stringify(
          {
                "colorTheme": "dark",
                "dateRange": "12M",
                "exchange": `${this.state.exchange}`,
                "showChart": true,
                "locale": "en"
              })
  }

  render() {

      const Changeexchange = (e) => { 

          this.setState({exchange: e.target.value})
          this.updateWidget()

      }  

      const SelectBox = () => (
          <div class="select-div">
          <select className="exchange" value={this.state.exchange} name="pagination" onChange={Changeexchange}>
            <option value="US"> USA (US Exchanges)</option>
            <option value="NASDAQ"> USA (NASDAQ)</option>
            <option value="NYSE"> USA (NYSE)</option>
            <option value="AMEX"> USA (NYSE ARCA)</option>
            <option value="OTC"> USA (OTC)  </option>
          </select>
          </div>
      )

      return(
        
      <div class="tradingview-widget-container" >
          <div style={{position:"absolute", top: "0px", left:"318px"}}>{SelectBox()}</div> 
          <div ref={this._ref} id='tradingView'></div>
       <div class="tradingview-widget-container__widget"> </div>
        {console.log(this.state.exchange)}
      </div>
      );
  }
 
}

您可以将 id 添加到您的元素(在本例中为 iframe),然后在 select onChange 调用中您可以根据存储的元素 ID 删除之前的 iframe,然后创建一个新元素.

Working Example With Comments

代码-

Changeexchange = (e) => {
    this.setState({ exchange: e.target.value });

    // Remove the existing DOM elem
    const elem = document.getElementById(this.currentDOMId);
    elem.parentNode.removeChild(elem);

    // Create a new elem with updated values
    // so that updated iframe will load
    const script = document.createElement("script");
    script.id = `dom-exchng-id-${this.state.exchange}`;
    this.currentDOMId = `dom-exchng-id-${this.state.exchange}`;
    script.src =
      "https://s3.tradingview.com/external-embedding/embed-widget-hotlists.js";
    script.async = true;
    this._ref.current.appendChild(script);
    script.innerHTML = JSON.stringify({
      colorTheme: "dark",
      dateRange: "12M",
      exchange: e.target.value,
      showChart: true,
      locale: "en"
    });
  };

仅供参考,我对您的代码进行了一些格式化,因为您在代码中将 className 称为 class