如何解决在Reactionic / react中动态创建具有独立状态/数据的UI元素的正确方法是什么
我不是前端开发人员,但我对JavaScript足够了解,可以解决此问题。但是,我最近开始与React框架结合使用Ionic。我是Ionic / React的初学者,在遇到这个问题之前,我发现它很有趣。
我正在开发的应用程序很简单。我正在通过服务器从Websockets(近)实时接收值,我想在UI中显示它们。为此,我在用户界面中有ItemSliding or SlidingComponents,可以在其中向右滑动以通过Websocket订阅(向服务器发送“获取消息”事件并开始使用消息/值),也可以向右滑动以退订并停止获取消息,或者我可以单击以从用户界面中删除ItemSliding。
由于我希望动态创建ItemSlidings或SlidingComponents,因此我搜索并发现可以循环浏览UI中的列表并即时创建元素,这是一个很棒的功能,我喜欢它,所以我m使用以下代码:
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)}
/>)
}
我没有显示所有代码库,因为我已经有数千行代码,因此我将其保持简单。如您所见,我遍历selectedTopics列表,并为该列表中的每个主题创建一个Slider(ItemSliding组件)。滑块是我正在创建的自定义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;
这是我用于滑块的代码。因此,我遍历了selectedTopics列表,并为该列表中的每个主题创建了一个Slider。如您所见,我将套接字作为道具传递,因为我想仅使用应用程序的一个全局套接字连接来发出事件并订阅来自服务器的响应。
正如我所说,问题是,有时我会收到值,并在console.log(在浏览器中)看到值来了,但它们未在UI中显示。其他时候显示值,但它们不在我想要的位置。例如,我收到topic1的值(应该是第一个Slider),但是在第二个Slider中显示了该值,这没有意义,因为我正在循环并为列表中的每个主题创建唯一的Slider,对?
我试图分配一个UUID而不是索引作为键,但是它没有用(实际上更糟)。然后,我尝试使用useEffect,但令人不寒而栗,它也不起作用。
我在这里做错什么了吗?我的方法或算法错误吗?我不确定在这种情况下的思维方式,因为我通常是React&Frontend的初学者。每个滑块应该具有自己的主题状态,并且根本不使用props.topic吗?我应该在这里使用useEffect吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。