我正在尝试在加载到react-native-snap-carousel中的图像上添加用户实时指示器。我正在工作,尽管当我只用一个元素(在线状态)更新数据数组时,它会渲染所有内容,使其全部关闭并重新加载。
我正在使用 socket.IO 发送消息进行更新,一切正常。我不想添加不同部分的所有代码,但可以根据需要添加。
我认为 React 的重点是它只重新渲染 DOM 中发生变化的部分。我知道基本上整个状态已经被复制、修改和保存,它只改变了一件事。我希望它只是更新一件事而不是重新加载所有内容。
我的代码是这样工作的:-
TrendingMovies.js
import {
View,
Text,
Image,
TouchableWithoutFeedback,
TouchableOpacity,
Dimensions,
StyleSheet,
} from "react-native";
import React from "react";
import Carousel from "react-native-snap-carousel";
import { useNavigation } from "@react-navigation/native";
import { AntDesign } from '@expo/vector-icons';
var { width, height } = Dimensions.get("window");
export default function TrendingMovies({ data }) {
const navigation = useNavigation();
const handleClick = (item) => {
console.log("Clicked");
};
return (
<View className="mb-8 mt-20">
<Text className="text-white text-xl mx-4 mb-5">Trending</Text>
<Carousel
data={data}
renderItem={({ item }) => (
<MovieCard handleClick={handleClick} item={item} />
)}
firstItem={1}
// loop={true}
inactiveSlideScale={0.85}
inactiveSlideOpacity={0.7}
sliderWidth={width}
itemWidth={width * 0.42}
slideStyle={{ display: "flex", alignItems: "center" }}
/>
</View>
);
}
const MovieCard = ({ item, handleClick }) => {
const filledStars = Math.floor(item.rating / 2);
const maxStars = Array(5 - filledStars).fill('staro');
const r = [...Array(filledStars).fill('star'), ...maxStars];
return (
<TouchableOpacity onPress={() => handleClick(item)}>
<Image
source={{ uri: 'https://{my_site}/users/'+item.userID+'/profile.jpg' }}
style={{
width: width * 0.4,
height: height * 0.2,
borderWidth: 2,
borderColor: "#fff",
}}
className="rounded-3xl"
/>
<Text style={{color:'white'}}>{item.status}</Text>
<View style={styles.rating}>
{r.map((type, index) => {
return <AntDesign key={index} name={type} size={20} color="yellow" />;
})}
</View>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
ratingNumber: { marginRight: 0, fontFamily: 'Menlo', fontSize: 0 },
rating: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginVertical: 4
},
});
它的导入和使用方式如下:-
import TrendingMovies from "../components/trendingMovies";
const [trending, setTrending] = useState([]);
API CALL TO GET DATA
当它从Socket.io接收到数据进行更新时,
const updateStatus = (data) => {
const new_data = trending.map(userID => {
if (userID === data.userID) {
// No change
return userID;
} else {
// Return a new circle 50px below
return {
...userID,
status: data.new_status,
};
}
});
// Re-render with the new array
setTrending(new_data);
}
如何阻止它重新加载所有内容,只需更改在线状态的一部分?目前,它看起来就像一个正常的页面完全重新加载。
谢谢
React 使用
key
属性来知道要重新渲染哪些元素。目前,所有 MovieCard 都没有键,因此当列表更新时,React 假定每个元素都是新的。
为每个电影卡提供一个密钥应该可以解决您的问题:
renderItem={({ item }) => (
<MovieCard
handleClick={handleClick}
item={item}
key={item.id}
/>
)}
确保密钥是唯一的。请参阅 https://react.dev/learn/rendering-lists#rules-of-keys 了解更多信息。