为什么 onClick 行为不当,有时不显示其背后的数据?

Why is onClick misbehaving and sometimes not showing data behind it?

typescript 的新手,现在已经使用它 2 天了,主要是为我的 streamlit 应用程序构建自定义组件。我创建了下面的导航栏,自定义组件是一个可以在边栏上单击的选项卡,尽管它的行为很奇怪。当我单击组件选项卡时,有时会加载相应的页面,有时却不会,如下所示:

custom navigation bar gif

我有一种预感,这可能是我编写打字稿代码的方式,也许是 onClick 函数。有没有更好的方法来做到这一点:

  1. return 通过 Streamlit.setComponentValue()
  2. 输入 labelName 的值
  3. 确保在单击组件选项卡时,它实际上加载了它后面的页面?我已经将 python 代码放置在下面:

Typescript 组件

import {
  Streamlit,
  StreamlitComponentBase,
  withStreamlitConnection,
} from "streamlit-component-lib"
import React, { ReactNode } from "react"

interface State {
  navLabel: string|number
}

class MyComponent extends StreamlitComponentBase<State> {
  public state = {navLabel: ""}

  public render = (): ReactNode => {

    const labelName = this.props.args["name"]
    const iconName = this.props.args["iconName"]

    const { theme } = this.props
    const styles: React.CSSProperties = {}

    return (
      <div className="navtab" onClick={this.onClicked}> 
        <div className="content">
        <input type="radio" name="indicator" id="input-data"/>
        <div className="list">
          <label htmlFor="input-data" className="input-data">              
            <span><i className="material-icons">{iconName}</i></span>
              <span className="text-display">{labelName}</span>
          </label>
          </div>
          </div>
        </div>
      
      
        )
      }

      private onClicked = (): void => {
        this.setState(
          prevState => ({navLabel: this.props.args["name"]}),
          () => Streamlit.setComponentValue(this.state.navLabel)
        )
      }

Python执行代码

import streamlit as st
import streamlit.components.v1 as components

def my_component(name, iconName, tabIndex, key=None):
   
    component_value = _component_func(name=name, iconName=iconName, tabIndex=tabIndex, key=key, default='Option')

    # We could modify the value returned from the component if we wanted.
    # There's no need to do this in our simple example - but it's an option.
    return component_value

with st.sidebar:
    test = my_component(name='Dashboard', iconName='dashboard', tabIndex=1, key="1")
    test_2 = my_component(name='Data Analysis', iconName='insights', tabIndex=2, key="2")
    test_3 = my_component(name='Testing', iconName='business', tabIndex=3, key="3")
    
if test == 'Dashboard':
    st.title("Dashboard")
    st.write('Name of option is {}'.format(test))

elif test_2 == 'Data Analysis':
    st.title("Data Analysis")
    st.write('Name of option is {}'.format(test_2))

elif test_3 == "Testing":
    st.title("Third one")

我能够使用 li 和 ul 元素解决这个问题:

import {
  Streamlit,
  StreamlitComponentBase,
  withStreamlitConnection,
} from "streamlit-component-lib"
import React, { ReactNode } from "react"

interface State {
  label: string,
  icon: string
}

class MyComponent extends StreamlitComponentBase<State> {

  public render = (): ReactNode => {

    const labelName:string[] = this.props.args["name"]
    const iconName:string[] = this.props.args["iconName"]

    let data:any[] = [];
    iconName.forEach((v,i) => 
      data= [...data, {"id":i+1, "label": labelName[i], "icon":v}]
    )   

    this.state = {
                  icon:data[0].icon,
                  label:data[0].label
                }
    const res = data.map(({id, icon, label}) => (
                                <span>
                                  <li className="tab"                                  
                                    key={id}
                                    onClick={() => this.setState(
                                      prevState => ({icon:icon, label:label}),
                                                    () => Streamlit.setComponentValue(label)
                                  )}><i className="material-icons">{icon}</i><span className="labelName">{label}</span></li></span>
                                ))

      return (
        
        <div className="navtab">
          <ul className="tab-options">
            {res}
          </ul> 
        </div>
    )
  }
 }