Javascript 动态创建UI元素并使其独立状态/数据处于React(离子/React)中的正确方法是什么

Javascript 动态创建UI元素并使其独立状态/数据处于React(离子/React)中的正确方法是什么,javascript,reactjs,ionic-framework,socket.io,ionic-react,Javascript,Reactjs,Ionic Framework,Socket.io,Ionic React,我不是一个前端开发人员,但我对JavaScript非常了解,足以解决这个问题。然而,我最近开始与离子结合使用React框架。我是一个离子/React的初学者,在我面对这个问题之前,学习它是很有趣的 我正在开发的应用程序很简单。我正在通过WebSocket从服务器实时(接近)接收值,并希望在UI中显示它们。为此,我在UI中设置了一个选项,在该选项中,我可以向右滑动通过websocket订阅(向服务器发送“获取消息”事件并开始使用消息/值),或者向右滑动取消订阅并停止获取消息,或者单击从UI中删除该

我不是一个前端开发人员,但我对JavaScript非常了解,足以解决这个问题。然而,我最近开始与离子结合使用React框架。我是一个离子/React的初学者,在我面对这个问题之前,学习它是很有趣的

我正在开发的应用程序很简单。我正在通过WebSocket从服务器实时(接近)接收值,并希望在UI中显示它们。为此,我在UI中设置了一个选项,在该选项中,我可以向右滑动通过websocket订阅(向服务器发送“获取消息”事件并开始使用消息/值),或者向右滑动取消订阅并停止获取消息,或者单击从UI中删除该项

由于我希望ItemSlidengs或SlidengComponents的创建是动态的,我搜索并发现我可以在UI中循环列表并动态创建元素,这是一个很棒的功能,我喜欢它,因此我使用以下代码:

import React, { useEffect, useState } from 'react';
const [selectedTopics, setSelectedTopics] = useState([]);  
.
.
. 
{selectedTopics.map((topic: any, idx: number) =>
        < Slider key={idx}  // I tried uuid here but it didn't work
          topic={topic}
          socket={socket}
          selectedTopics={selectedTopics}
          setSelectedTopics={(topics: any) => setSelectedTopics(topics)}

        />)
      }
import React,{useffect,useState}来自“React”;
常量[selectedTopics,setSelectedTopics]=useState([]);
.
.
. 
{selectedTopics.map((主题:any,idx:number)=>
setSelectedTopics(主题)}
/>)
}
我没有显示所有的代码库,因为我已经有数千行代码,所以我保持简单。如您所见,我在selectedTopics列表上循环,并为列表中的每个主题创建一个滑块(ItemSlidering组件)。滑块是我正在创建的自定义react组件,在这里我将发布一个结构的最小示例:

import React, { useState, useRef, useEffect} from 'react';
import { IonItemSliding, IonItemOptions, IonItemOption, IonItem, IonLabel, IonNote, IonIcon, IonSpinner } from '@ionic/react';
import { trash, ellipse } from 'ionicons/icons';



const Slider: React.FC<{
  socket: SocketIOClient.Socket;
  topic: any;
  selectedTopics: any;
  setSelectedTopics: any;
}> = (props) => {

  const [realTimeValue, setRealTimeValue] = useState<string>("");
  const [loading, setLoading] = useState<boolean>(false);
  const [subscribed, setSubscribed] = useState<boolean>(false);

  
  const onSubscribe = (topic: any) => {
    
    props.socket.on("onSubscribe", (data: any) => {

      try {
        const name = data.Name;
        const payload = data.Value;

        console.log(`received response with name: ${name} and payload: ${payload}`);
      if (topic.name === name) {
        console.log(`topic received= ${name} correspond to tpic name = ${topic.name}`);
        setSubscribed(true);
        setRealTimeValue(payload);
        setLoading(false);

      }
      else {

        console.log(`received topic = ${name} but current was ${topic.name} `);
      }
      }
      catch(err) {
        console.log("error", err);
      }
      

    });
  }

  const subscribe = (topic: any) => {

    const req = {
          subscribe: topic.Topic,
        }
     
    props.socket.emit('subscribe', req);
    setLoading(true);
    onSubscribe(topic);


  }

  const unsubscribe = (topic: any) => {

    const req = {
          unsubscribe: topic.Topic,
        }

    props.socket.emit('unsubscribe', req);
    setSubscribed(false);
    setRealTimeValue("");
    setLoading(false);
  }

  const deleteTopic = (topic: any) => {
    console.log('delete this topic : ' + topic.name);
    unsubscribe(topic);
    const newSelectedTopics = props.selectedTopics.filter((topicObj: any) => topic.name !== topicObj.Name);
    props.setSelectedTopics(newSelectedTopics);

  }
  
  return (
    <IonItemSliding>
      <IonItemOptions onIonSwipe={() => subscribe(props.topic)} side="start">

      </IonItemOptions>

      <IonItem color={"light"}>
        <IonLabel>
        <IonIcon className="subscription-icon"
            color={loading ? "warning" : subscribed ? "success" : "danger"}
            icon={ellipse}
          >
          </IonIcon>
          {props.topic.name}
        </IonLabel>

        <IonNote slot="end" color="dark">
          {subscribed ? realTimeValue : loading ? <IonSpinner name="circles" /> : ""}
        </IonNote>
      </IonItem>

      <IonItemOptions onIonSwipe={() => unsubscribe(props.topic)} side="end">
        <IonItemOption color="danger" onClick={() => { deleteTopic(props.topic) }}>
          <IonIcon icon={trash}></IonIcon>
        </IonItemOption>
      </IonItemOptions>
    </IonItemSliding>

  );
};

export default Slider;
import React,{useState,useRef,useffect}来自'React';
从'@ionic/react'导入{IonItemSlideing,IonItemOptions,IonItemOption,IonItem,IonLabel,IonNote,IonIcon,IonSpinner};
从“ionicons/icons”导入{trash,ellipse};
常量滑块:React.FC=(道具)=>{
常量[realTimeValue,setRealTimeValue]=useState(“”);
const[loading,setLoading]=useState(false);
const[subscribed,setSubscribed]=使用状态(false);
const onSubscribe=(主题:any)=>{
props.socket.on(“onSubscribe”,数据:any)=>{
试一试{
const name=data.name;
常量有效载荷=数据值;
log(`received response with name:${name}和payload:${payload}`);
if(topic.name==name){
log(`topic received=${name}对应于tpic name=${topic.name}`);
设置订阅(真实);
setRealTimeValue(有效载荷);
设置加载(假);
}
否则{
log(`received topic=${name},但当前为${topic.name}`);
}
}
捕捉(错误){
日志(“错误”,err);
}
});
}
const subscribe=(主题:any)=>{
常数要求={
订阅:topic.topic,
}
props.socket.emit('subscribe',req');
设置加载(真);
订阅(主题);
}
const unsubscribe=(主题:any)=>{
常数要求={
取消订阅:主题。主题,
}
props.socket.emit('unsubscribe',req');
设置订阅(假);
setRealTimeValue(“”);
设置加载(假);
}
常量deleteTopic=(主题:任意)=>{
console.log('删除此主题:'+主题名称);
退订(主题);
const newSelectedTopics=props.selectedTopics.filter((topicObj:any)=>topic.name!==topicObj.name);
道具。设置选定道具(新选定道具);
}
返回(
订阅(props.topic)}side=“开始”>
{props.topic.name}
{订阅的?realTimeValue:正在加载?:“”
取消订阅(props.topic)}side=“end”>
{deleteTopic(props.topic)}>
);
};
导出默认滑块;
这就是我用于滑块的代码。因此,我在selectedTopics列表中循环,并为该列表中的每个主题创建一个滑块。正如您所看到的,我将套接字作为道具传递,因为我希望仅使用应用程序的一个全局套接字连接从服务器发出事件并订阅响应

正如我所说的,问题是,有时我接收到值,并在console.log(在浏览器中)中看到值出现了,但它们没有显示在UI中。其他时候会显示值,但它们不在我想要的位置。例如,我收到topic1的值(应该是第一个滑块),但它显示在第二个滑块中,这没有意义,因为我正在循环并为列表中的每个主题创建一个唯一的滑块,对吗

我尝试分配一个UUID而不是索引作为键,但没有成功(事实上更糟)。然后我试着用它,但它让人兴奋,也不起作用

我做错什么了吗?我的方法或算法错了吗?在这种情况下,我不确定自己的思维方式,因为我一般是react&frontend的初学者。每个滑块是否应该有自己的主题状态,而不使用props.topic?我应该在这里使用useffect吗