编辑 - 我重新构建了流程以使其不那么冗长。希望这更容易消化
我有一组屏幕(黄色、橙色、绿色等),每个屏幕都有 5 张卡,用于显示视频缩略图、标题等数组。每张卡可以容纳任意数量的缩略图。用户将视频/缩略图添加到这些卡(集合)的方式是通过包含数据的模式,并且每个项目都有一个复选框。选择复选框并关闭模式后,它们将添加到卡片中。
这有效。除了,当我从另一张卡打开模式时,先前选择的复选框已被选中。我需要使用从打开它的卡中选择的复选框来打开每个模式
注意:复选框组件来自 React Native Paper - 请参阅此处。它没有
value
属性。它使用我已经在实施的 status
。
此外,每张卡都位于单独的文件中,以保持关注点分离,并且不会意外混合道具值。然而,该复选框坚持记住最后的选择。
这是黄屏的逻辑代码
// This function gets triggered by the checkbox selection and
// populates the state `selectedwaza`
// it also handles the checked and unchecked status
const selectItem = (item, index) => {
const newData = [...dropdowndata];
const newItem = newData[index];
newItem.checked = !item.checked;
setChecked(!checked)
setDropdownData(newData);
if (newItem.checked) {
if (!selectedwaza.includes(newItem)) {
setSelectedWaza(prev => [...prev, newItem]);
}
} else {
setSelectedWaza(prev => prev.filter(i => i.title !== newItem.title));
}
}
我认为如下:
// I mad the items to pick from and assign a checkbox to each item
{dropdown_collection.map((item, index) => {
return (
<View key={index}>
<Text style={{color: activeColors.textcolor}} >
{item.title}
</Text>
<Checkbox.Item
mode='android'
color={activeColors.primary}
status={item.checked ? 'checked' : 'unchecked'}
onPress={() => selectItem(item, index)}
/>
</View>
)
}
})}
编辑2我可以看到,尽管复选框保持选中状态,但它们的值并未保留。我仍然可以打开下一组卡片并选择我想要的内容,它只会添加新选择的内容并忽略上次使用中已经记住的内容。然而,这是不切实际的,因为如果我想添加一个已显示为选定的选项,我必须先取消选择它,然后再次选择它。我认为一个简单的“关闭模式时清除复选框”方法将是一个很好的技巧。但这也行不通。我正在发布有问题的函数,以防其他人看到这个并想帮助我
const selectItem = (item, index) => {
const newData = [...dropdownCollection];
const newItem = newData[index];
newItem.checked = !item.checked;
setChecked(!checked)
if (newItem.checked) {
if (!selectedwaza.includes(newItem)) {
setSelectedWaza(prev => [...prev, newItem]);
}
} else {
setSelectedWaza(prev => prev.filter(i => i.title !== newItem.title));
}
}
// Function to clear all checkboxes
const handleCloseModal = () => {
setModalVisible(false);
const clearedData = dropdown_collection.map(item => ({
...item,
checked: false
}));
// Update your state with the cleared data
setDropdownCollection(clearedData);
};
对于那些需要更多代码来查看的人,请参阅下面的整个页面。其他只需要相关代码的人请忽略下面
import React, {useContext, useState, useRef, useEffect} from 'react';
import { StyleSheet, View, Text, TouchableOpacity, Image, Animated, Pressable, Modal, ActivityIndicator } from 'react-native'
import { colors } from '../../../../assets/theme/config';
import { ThemeContext } from '../../../../context/ThemeContext';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { useNavigation } from '@react-navigation/native';
import { Checkbox } from 'react-native-paper';
import SearchField from '../../../../components/SearchField';
import ashiwaza from '../../../../assets/data/nagewaza/ashiwaza';
import koshiwaza from '../../../../assets/data/nagewaza/koshiwaza';
import masutemiwaza from '../../../../assets/data/nagewaza/masutemiwaza';
import yokosutemiwaza from '../../../../assets/data/nagewaza/yokosutemiwaza';
import tewaza from '../../../../assets/data/nagewaza/tewaza';
const dropdown_collection = [...tewaza, ...ashiwaza, ...koshiwaza, ...masutemiwaza, ...yokosutemiwaza]
import {db, auth} from '../../../../firebase';
import {onAuthStateChanged} from 'firebase/auth';
import { doc, getDoc, updateDoc, setDoc } from 'firebase/firestore';
const ITEM_SIZE = 180;
const ITEM_HEIGHT = 145;
const QTY = 8
const GokyoNowaza = () => {
const [index, setIndex] = useState(0);
const [waza, setWaza] = useState([])
const [checked, setChecked] = useState(false)
const [selectedwaza, setSelectedWaza] = useState([])
const [dropdownCollection, setDropdownCollection] = useState(dropdown_collection);
const [modalVisible, setModalVisible] = useState(false);
const [value, setValue] = useState("");
const isLoading = false
const ref = useRef(null);
const {theme} = useContext(ThemeContext)
let activeColors = colors[theme.mode]
const navigation = useNavigation();
// build the collection from selecting the checkboxes
const selectItem = (item, index) => {
const newData = [...dropdownCollection];
const newItem = newData[index];
newItem.checked = !item.checked;
setChecked(!checked)
if (newItem.checked) {
if (!selectedwaza.includes(newItem)) {
setSelectedWaza(prev => [...prev, newItem]);
}
} else {
setSelectedWaza(prev => prev.filter(i => i.title !== newItem.title));
}
}
// Function to clear all checkboxes
const handleCloseModal = () => {
setModalVisible(false);
const clearedData = dropdown_collection.map(item => ({
...item,
checked: false
}));
// Update your state with the cleared data
setDropdownCollection(clearedData);
};
//set collection to data
const handleTestCollection = async () => {
const userId = auth.currentUser.uid;
const docRef = doc(db, 'useraccounts', userId);
try {
const docSnap = await getDoc(docRef);
// Prepare the data to be set or updated
const gokyuData = docSnap.exists() && docSnap.data().gokyu
? docSnap.data().gokyu
: {};
gokyuData.gokyoNoWaza = Array.isArray(selectedwaza)
? [...selectedwaza]
: gokyuData.gokyoNoWaza || [];
// Set or update the document
await setDoc(docRef, { gokyu: gokyuData }, { merge: true });
console.log("Document successfully updated!");
} catch (error) {
console.error("Error updating document: ", error);
}
}
//display the colleciton on load
useEffect(() => {
const getUser = () => {
onAuthStateChanged(auth, (user) => {
if(user) {
const userId = auth.currentUser.uid;
user !== null || user !== undefined
const docRef = doc(db, 'useraccounts', userId);
getDoc(docRef).then((docSnap) => {
const data = docSnap.data().gokyu?.gokyoNoWaza || [];
if (docSnap.exists()){
setSelectedWaza(data);
} else {
console.log("nothing here");
}
});
}
});
}
getUser();
}, []);
return (
<View style={[{backgroundColor: activeColors.bgalt}, styles.card]}>
<View style={styles.sectionLabelAndButton}>
<View>
<View>
<Text style={[{color: activeColors.textcolor, fontSize:18, fontWeight:'bold'}]}>
Gokyo No Waza
</Text>
</View>
<View>
<Text style={[{color: activeColors.textcolor, fontSize:18, fontWeight:'normal'}]}>
Select {QTY} throws
</Text>
</View>
</View>
<View style={styles.buttons} >
<TouchableOpacity
onPress={() => handleTestCollection()}
style={[{backgroundColor:activeColors.primary}, styles.addiconbutton]}>
<Icon name="content-save" size={24} color={activeColors.white} />
</TouchableOpacity>
<TouchableOpacity
onPress={() => setModalVisible(true)}
style={[{backgroundColor:activeColors.primary}, styles.addiconbutton]}>
<Icon name="plus" size={24} color={activeColors.white} />
</TouchableOpacity>
</View>
</View>
<Animated.FlatList
ref={ref}
data={selectedwaza}
horizontal
initialNumToRender={10}
initialScrollIndex={index}
keyExtractor={(item, index) => index.toString()}
showsHorizontalScrollIndicator={false}
snapToInterval={ITEM_SIZE}
snapToOffsets={[...Array(waza.length).keys()].map(i => i * ITEM_SIZE)}
decelerationRate={0}
bounces={false}
scrollEventThrottle={16}
onEndReachedThreshold={0.5}
onEndReached={() => {
setWaza([...waza]);
}}
contentContainerStyle={{
alignItems: 'flex-start',
}}
renderItem={
({item, index: fIndex}) => {
return (
<View key={fIndex} style={{width:ITEM_SIZE * .6, marginVertical:20, marginRight: 20}}>
<View style={[{color: activeColors.textcolor, backgroundColor: activeColors.bgalt,}, styles.counter]}>
<Text style={{color: activeColors.textcolor}}>{fIndex + 1}</Text>
</View>
<View style={[styles.overlay]}>
<TouchableOpacity
onPress={() => navigation.navigate('TechniqueDetails', {data: item})}
style={[{backgroundColor:activeColors.primary}, styles.playbutton]}>
<Icon name="play" size={24} color={activeColors.white} />
</TouchableOpacity>
</View>
<Animated.View>
<Image source={{ uri: `https://judopedia.wiki/assets/images/${item.thumbnail}` }}
style={styles.thumbnail}/>
<Text
numberOfLines={2}
style={{
width: ITEM_SIZE * .6,
color:activeColors.textcolor,
fontWeight: 'bold'
}}>
{item.title}
</Text>
</Animated.View>
</View>
)
}
}
/>
<Modal animationType="slide" visible={modalVisible} transparent={true}>
<View
style={[{backgroundColor: activeColors.overlay}, styles.container]}>
{isLoading && <ActivityIndicator size={70} color={colors.tertiary} />}
{!isLoading && (
<View style={[styles.modalView, { backgroundColor: activeColors.bgalt }]}>
<View style={{width: "100%", alignItems: "center", justifyContent:"space-between", flexDirection:"row"}}>
<Text style={[{color:activeColors.primary }, styles.modalheading]}>
Techniques
</Text>
<Pressable onPress={handleCloseModal}>
<Icon name="close" size={24} color={activeColors.textcolor} />
</Pressable>
</View>
<View style={styles.decisionRow}>
<SearchField value={value} onChangeText={setValue} style={{backgroundColor: activeColors.bg}} />
<View style={[{backgroundColor: activeColors.bgalt}, styles.searchcontainer]}>
{dropdown_collection.map((item, index) => {
if(value === "" ) {
return null
} else if(
item.title.toLowerCase().includes(value.toLowerCase()) || item.english.toLowerCase().includes(value.toLowerCase())
)
{
return (
<View key={index} style={styles.searchitems}>
<View style={styles.metadata}>
<Image source={{ uri: `https://judopedia.wiki/assets/images/${item.thumbnail}` }} style={styles.searchresultsthumbnail}/>
<View>
<Text style={{color: activeColors.textcolor}} >{item.title}</Text>
<Text style={{color: activeColors.textcolor, fontSize:12}} >{item.english}</Text>
</View>
</View>
<View style={styles.buttongroup}>
<Checkbox.Item
mode='android'
color={activeColors.primary}
status={item.checked ? 'checked' : 'unchecked'}
onPress={() => selectItem(item, index)}
/>
</View>
</View>
)
}
})}
</View>
</View>
</View>
)}
</View>
</Modal>
</View>
)
}
export default GokyoNowaza
在您在此部分提供的代码中:
dropdown_collection.map((item, index) => {
if (value === '') {
return null;
} else if (
item.title.toLowerCase().includes(value.toLowerCase()) ||
item.english.toLowerCase().includes(value.toLowerCase())
) {
return (
<View key={index} style={styles.searchitems}>
<View style={styles.metadata}>
<Image
source={{ uri: `https://judopedia.wiki/assets/images/${item.thumbnail}` }}
style={styles.searchresultsthumbnail}
/>
<View>
<Text style={{ color: activeColors.textcolor }}>{item.title}</Text>
<Text style={{ color: activeColors.textcolor, fontSize: 12 }}>{item.english}</Text>
</View>
</View>
<View style={styles.buttongroup}>
<Checkbox.Item
mode='android'
color={activeColors.primary}
status={item.checked ? 'checked' : 'unchecked'}
onPress={() => selectItem(item, index)}
/>
</View>
</View>
);
}
});
您应该绘制状态图而不是
dropdown_collection
。 handleCloseModal
清除状态 dropdownCollection
的数据,但您正在返回 dropdown_collection
。