Expo 中的 FlatList 在再次刷新项目后加载并渲染项目两次导致重复键
FlatList in Expo loads after refreshing the project again and renders the items twice causing duplicate keys
我实际上是在尝试将订单作为存储在 firebase 中的对象获取,并将它们显示在历史屏幕中,但是平面列表在初始渲染时显示一个空屏幕,并在刷新时再次显示项目,导致项目显示两次,因此导致重复键??我应该如何让 flatlist 第一次渲染东西?
export const HistoryScreen = () => {
const [isLoading, setIsLoading] = useState(true);
const [ list, setList] = useState([]);
var json = [];
var keys = [];
const firebaseRef = firebase.database().ref(`Orders/${orderData.firebaseUserId}`);
const getJson = async () => {
await firebaseRef.on("value" , (snapshot) => {
json = snapshot.val();
});
}
const SendingData = async () => {
await getJson();
keys = Object.keys(json);
//Mapping Data
keys.map((key) => {
let k = json[key];
let appliance = Data.find((app) => app.title === k["Appliance_Name"]);
let obj = {"id" : key, "title" : k['Appliance_Name'], "service" : k['Service_Requested'],
"time" : k['Time'], "status" : k["Status"], "image" : appliance.image};
list.push(obj);
})
}
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 3000);
}, []);
useEffect(() => {
SendingData();
})
return (
<SafeArea>
<LinearGradient style={styles.screen} colors={[color.screenBackground.g3, color.screenBackground.g2,color.screenBackground.g2, color.screenBackground.g3]}>
{isLoading ? (
<View style={styles.loader}>
<ActivityIndicator size="large" color={color.screenBackground.g4} />
</View>
) : (
<View style={styles.screen}>
<Appointments>Your Appointments</Appointments>
<OrderCard>
<Scroll>
<FlatList style={styles.list}
data = {list}
renderItem = { ({ item }) => (
<Item>
<View style={styles.view}>
<View>
<Image source={item.image} resizeMode='contain' style={styles.image}/>
</View>
<View style={styles.container}>
<Title>{item.title}</Title>
<Service>Job : {item.service}</Service>
<Time>Booking Time : {item.time}</Time>
<ID>Appointment ID : {item.id}</ID>
</View>
</View>
<Status>Status : {item.status}</Status>
</Item>
)}
keyExtractor = {item => item.id}
/>
</Scroll>
</OrderCard>
</View>
)}
</LinearGradient>
</SafeArea>
);
}
您需要增强用于获取数据的方法。
首先你需要使用 setList
添加项目而不是 list.push
。
const [isLoading, setIsLoading] = useState(true);
const [ list, setList] = useState([]);
const firebaseRef = firebase.database().ref(`Orders/${orderData.firebaseUserId}`);
const SendingData = async () => {
let data = []
let tmp_keys;
await firebaseRef.on("value" , (snapshot) => {
let json = snapshot.val();
tmp_keys = Object.keys(json);
tmp_keys.map((key) => {
let k = json[key];
let appliance = Data.find((app) => app.title === k["Appliance_Name"]);
let obj = {"id" : key, "title" : k['Appliance_Name'], "service" : k['Service_Requested'],
"time" : k['Time'], "status" : k["Status"], "image" : appliance.image};
data.push(obj)
});
setLits(data)
})
}
也可以在 SendingData
结束时将 isLoading 设置为 false
我实际上是在尝试将订单作为存储在 firebase 中的对象获取,并将它们显示在历史屏幕中,但是平面列表在初始渲染时显示一个空屏幕,并在刷新时再次显示项目,导致项目显示两次,因此导致重复键??我应该如何让 flatlist 第一次渲染东西?
export const HistoryScreen = () => {
const [isLoading, setIsLoading] = useState(true);
const [ list, setList] = useState([]);
var json = [];
var keys = [];
const firebaseRef = firebase.database().ref(`Orders/${orderData.firebaseUserId}`);
const getJson = async () => {
await firebaseRef.on("value" , (snapshot) => {
json = snapshot.val();
});
}
const SendingData = async () => {
await getJson();
keys = Object.keys(json);
//Mapping Data
keys.map((key) => {
let k = json[key];
let appliance = Data.find((app) => app.title === k["Appliance_Name"]);
let obj = {"id" : key, "title" : k['Appliance_Name'], "service" : k['Service_Requested'],
"time" : k['Time'], "status" : k["Status"], "image" : appliance.image};
list.push(obj);
})
}
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 3000);
}, []);
useEffect(() => {
SendingData();
})
return (
<SafeArea>
<LinearGradient style={styles.screen} colors={[color.screenBackground.g3, color.screenBackground.g2,color.screenBackground.g2, color.screenBackground.g3]}>
{isLoading ? (
<View style={styles.loader}>
<ActivityIndicator size="large" color={color.screenBackground.g4} />
</View>
) : (
<View style={styles.screen}>
<Appointments>Your Appointments</Appointments>
<OrderCard>
<Scroll>
<FlatList style={styles.list}
data = {list}
renderItem = { ({ item }) => (
<Item>
<View style={styles.view}>
<View>
<Image source={item.image} resizeMode='contain' style={styles.image}/>
</View>
<View style={styles.container}>
<Title>{item.title}</Title>
<Service>Job : {item.service}</Service>
<Time>Booking Time : {item.time}</Time>
<ID>Appointment ID : {item.id}</ID>
</View>
</View>
<Status>Status : {item.status}</Status>
</Item>
)}
keyExtractor = {item => item.id}
/>
</Scroll>
</OrderCard>
</View>
)}
</LinearGradient>
</SafeArea>
);
}
您需要增强用于获取数据的方法。
首先你需要使用 setList
添加项目而不是 list.push
。
const [isLoading, setIsLoading] = useState(true);
const [ list, setList] = useState([]);
const firebaseRef = firebase.database().ref(`Orders/${orderData.firebaseUserId}`);
const SendingData = async () => {
let data = []
let tmp_keys;
await firebaseRef.on("value" , (snapshot) => {
let json = snapshot.val();
tmp_keys = Object.keys(json);
tmp_keys.map((key) => {
let k = json[key];
let appliance = Data.find((app) => app.title === k["Appliance_Name"]);
let obj = {"id" : key, "title" : k['Appliance_Name'], "service" : k['Service_Requested'],
"time" : k['Time'], "status" : k["Status"], "image" : appliance.image};
data.push(obj)
});
setLits(data)
})
}
也可以在 SendingData