使用React Native更新数组中的对象后重新渲染的问题

问题描述 投票:0回答:1

我正在尝试在加载到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);

    }

如何阻止它重新加载所有内容,只需更改在线状态的一部分?目前,它看起来就像一个正常的页面完全重新加载。

谢谢

reactjs react-native react-hooks state
1个回答
0
投票

React 使用

key
属性来知道要重新渲染哪些元素。目前,所有 MovieCard 都没有键,因此当列表更新时,React 假定每个元素都是新的。

为每个电影卡提供一个密钥应该可以解决您的问题:

        renderItem={({ item }) => (
          <MovieCard
            handleClick={handleClick}
            item={item}
            key={item.id}
          />
        )}

确保密钥是唯一的。请参阅 https://react.dev/learn/rendering-lists#rules-of-keys 了解更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.