私はReact Native(および正直に言うとReact / Javascript全般)に非常に慣れておらず、非常に行き詰まっています。Flatlist を使用して雑用のリストをレンダリングする雑用追跡アプリがあります。これは、React Native Gesture Handler Swipeable を使用してスワイプ/チェックオフできます。
家事リストの上に、完了した家事の総数を示すタグが必要です (プレースホルダーは現在、「?? 家事完了」と表示されています)。これには、1) Flatlist コンポーネントからレンダリングされた ChoreListItems の数、および 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;