获取从FlatList中呈现的项目总数,然后根据项目状态的变化更新该数字



我对React Native(和React/Javascript一般来说是诚实的)非常陌生,并且非常卡住。我有一个家务跟踪应用程序,它使用Flatlist呈现家务列表,然后可以使用React Native Gesture Handler Swipeable滑动/勾选。

我想在杂务列表上方添加一个标签,显示完成的杂务总数(占位符当前显示"?? ?)家务complete")。我知道这需要找到1)有多少我的ChoreListItems是从Flatlist组件中呈现的,然后2)这些项目中有多少具有"iscomplete"状态。我有几个嵌套/可重用的组件,因为这个屏幕会有几个版本(洗衣、厨房、浴室等),我知道这让我更困惑。我觉得这里可能有一个明显的答案,但我甚至不知道如何开始打开它。

下面是ChoreListItem(它是从Flatlist中渲染出来的,并且可以被滑动):

import React, { useState, useRef} from 'react';
import { Animated, Image, StyleSheet, Text, TouchableWithoutFeedback, View } from 'react-native';
import Swipeable from 'react-native-gesture-handler/Swipeable';
import appStyles from '../config/appStyles';
import colors from '../config/colors';
import BodyText from '../config/BodyText';
function ChoreListItem({title}) { 
const [isComplete, setIsComplete] = useState(false);
const swipeableRef = useRef();
//Track interaction occurs on left swipe
const LeftActions = (progress, dragX) => {
const scale = dragX.interpolate({
inputRange: [0, 100],
outputRange: [0,1],
extrapolate: 'clamp',
});
if (isComplete == false) {
return (
<View style ={[appStyles.card, styles.leftActions]}>
<Animated.Text style={[styles.swipeText, {transform: [{scale}], fontSize:16, }]}>Swipe to track</Animated.Text>
<Image source={require('../assets/control_arrow_right.png')} style={{alignItems:'center',tintColor:colors.baseWhite,}}/>
</View>
);
}
};
//Untrack button renders on right swipe
const RightActions = (progress, dragX) => {
const scale = dragX.interpolate({
inputRange: [-100,0],
outputRange: [1,0],
extrapolate: 'clamp',
});
if (isComplete === true) {
return (
<TouchableWithoutFeedback onPress={closeSwipeable}>
<View style ={[appStyles.card, styles.rightActions]}>
<Animated.Text style={[styles.swipeText,{transform: [{scale}], fontSize:16, }]}>Tap to untrack</Animated.Text>
</View>
</TouchableWithoutFeedback>
);
}
};
//Closes swiped action and changes state
const closeSwipeable = () => {
if (isComplete===false) {
setIsComplete (true);
console.log(title + ' tracked');
} else {
setIsComplete(false);
console.log(title + ' untracked');
}
}
return (
<Swipeable 
ref={swipeableRef}
state={isComplete}
renderLeftActions={LeftActions} 
leftThreshold={20}
rightThreshold={10}
overshootRight={false}
renderRightActions={RightActions}
onSwipeableLeftOpen={closeSwipeable}
>
<View style={[appStyles.card, styles.choreListItem]}>
<BodyText style={{textDecorationLine: isComplete ? "line-through" : "none"}}>{title}</BodyText>
<Image style={[styles.checkmark, {display: isComplete ? "flex" : "none"}]} source={require('../assets/checkmark_large.png')}/>
</View> 
</Swipeable>
);
}
export default ChoreListItem;
const styles = StyleSheet.create({
checkmark: {
width:16,
height:16,
},
choreListItem: {
paddingLeft:16,
paddingRight:16,
paddingTop:20,
paddingBottom:20, 
marginBottom:16,
flex:1,
flexDirection:'row',
alignItems:'center',
justifyContent:'space-between'
},
swipeText: {
color: colors.baseWhite,
},
leftActions: {
paddingLeft:16,
paddingRight:16,
paddingTop:20,
paddingBottom:20,
marginBottom: 16,
backgroundColor: colors.primaryBlue,
flex: 1,
shadowColor: 'transparent',
alignItems:'center',
flexDirection:'row'
},
rightActions: {
paddingLeft:16,
paddingRight:16,
paddingTop:20,
paddingBottom:20,
marginBottom: 16,
backgroundColor: colors.primaryPurple,
shadowColor: 'transparent',
alignItems:'flex-end',
flexDirection:'row',

},
});

下面是ChoreList(包括Flatlist组件):

import React from 'react';
import {FlatList, StyleSheet, Text, View} from 'react-native';
import appStyles from '../config/appStyles';
import colors from '../config/colors';
import ChoreListItem from '../components/ChoreListItem';
import SectionTitleBar from '../components/SectionTitleBar';
function ChoreList({getCategory}) {
return (
<View style={appStyles.containerPadding}>
{/* <SectionTitleBar title="Today"/> */}
<View>
<FlatList
data = {getCategory}
renderItem={({item}) =>
<ChoreListItem title={item.title} />
}  
keyExtractor={(item) => item.title.toString()}
/>
</View>
</View>
);
}
export default ChoreList;
const styles = StyleSheet.create({
choreListItem: {
padding:16,
marginBottom:16,
},
});

下面是包含所有道具的组件/屏幕:

import React from 'react';
import { Text, View } from 'react-native';
import choreCats from '../config/choreCats';
import choreItems from '../config/choreItems';
import colors from '../config/colors';
import ChoreList from '../components/ChoreList';
import PageHeader_TitleIllo from '../components/pageHeaders/PageHeader_TitleIllo';
import Screen from '../components/Screen';
function LaundryChoresScreen() {
const choreCategory = choreCats[4];
return (
<Screen>
<PageHeader_TitleIllo 
category={choreCategory.category}
image={choreCategory.image}
bgColor={choreCategory.bgColor}
/>
<Text style={{padding:8, backgroundColor:colors.blueHueMedium, alignSelf:'flex-start', marginTop: 8, marginBottom: 8}}>?? Chores complete</Text>
<View style={{backgroundColor:colors.baseFog,}}>
<ChoreList getCategory={choreItems.filter(({category})=>category=== "laundry")}/>
</View>
</Screen>
);
}
export default LaundryChoresScreen;

有几种不同的方法可以实现这一点,但最好的方法可能是将已完成的杂务状态提升到与这个新功能共享的水平。您可以通过跟踪需要共享的最高位置的完整/不完整质量来做到这一点。目前,这是你的LaundryChoresScreen组件。

然后需要将更改杂务数组的函数传递给ChoreListItem的props,以便在需要更改杂务状态时调用。这个过程被称为支柱钻井。许多人对单调乏味的prop钻取感到沮丧,并选择创建一个全局状态来从应用程序中的任何地方管理事物(使用Contexts或Redux),但对于这种情况,这些可能是多余的。

最新更新