使用react native更新数组中状态的对象后重新呈现的问题

dnph8jn4  于 6个月前  发布在  React
关注(0)|答案(1)|浏览(93)

我试图添加一个用户活指标上的图像是在一个加载到一个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);

    }


我如何阻止它重新加载所有内容,只是改变在线状态的一部分?在那一刻,它看起来像一个正常的页面完全重新加载。
谢谢

nkcskrwz

nkcskrwz1#

React使用key prop来知道要重新渲染哪些元素。现在,MovieCards都没有键,所以当列表更新时,React假设每个元素都是新的。
给每个电影卡一个密钥应该可以解决你的问题:

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

字符串
请确保密钥是唯一的。有关详细信息,请参阅https://react.dev/learn/rendering-lists#rules-of-keys。

相关问题