React native : Flatlist inside scrollview - javascript

My goal is for this entire block to be scrollable.
I tried all kinds of ways to achieve the goal but without success.
I tried with ListHeaderComponent and moved the entire top view to it and it didn't work.
And I also tried <FlatList nestedScrollEnabled />
And it didn't work either.
What is the correct way to reach the scroll?
I come from here :
const renderAccordians = () => {
const items: JSX.Element[] = [];
areaData.forEach(item => {
items.push(<Accordian item={item} key={item.title} />);
});
return items;
};
To here :
return (
<View>
<View style={styles.row}>
<TouchableOpacity onPress={() => onClickFather()}>
<MaterialIcons size={24} name={data.checked ? 'check-box' : 'check-box-outline-blank'} color={'black'} />
</TouchableOpacity>
<Text style={[styles.title]}>{data.title}</Text>
<TouchableOpacity style={styles.row} onPress={() => toggleExpand()}>
<MaterialIcons name={expanded ? 'arrow-drop-up' : 'arrow-drop-down'} size={30} color={'black'} />
</TouchableOpacity>
</View>
<View style={styles.parentHr} />
{expanded && (
<FlatList
data={data.data}
numColumns={1}
scrollEnabled={false}
renderItem={({ item, index }) => (
<View>
<TouchableOpacity style={[styles.childRow, styles.button]} onPress={() => onClick(index)}>
<MaterialIcons
size={24}
name={item.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
<Text style={[styles.itemInActive]}>{item.key}</Text>
</TouchableOpacity>
<View style={styles.childHr} />
</View>
)}
/>
)}
</View>
);

Since your FlatList will be part of an Accordion component, you "can't" embed the ExpandButton inside the Flatlist > ListHeaderComponent ... cause It'll simply hide the whole FlatList along with it's Header when you collapse your accorddion...
keyExtractor is also missing in your FlatList .. I added index as a key here which is not recommended BTW, you better use a unique field in your listItem like id...
return (
<View style={{ flex: 1}}> // <<--- Look here
<View style={styles.row}>
<TouchableOpacity onPress={() => onClickFather()}>
<MaterialIcons
size={24}
name={data.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
</TouchableOpacity>
<Text style={[styles.title]}>{data.title}</Text>
<TouchableOpacity style={styles.row} onPress={() => toggleExpand()}>
<MaterialIcons
name={expanded ? 'arrow-drop-up' : 'arrow-drop-down'}
size={30}
color={'black'}
/>
</TouchableOpacity>
</View>
<View style={styles.parentHr} />
{expanded && (
<FlatList
data={data.data}
numColumns={1}
scrollEnabled={true} // <<--- Look here
keyExtractor={(_, index) => index.toString()} // <<=== Look here
contentContainerStyle={{flexGrow: 1}} // <<--- Look here
renderItem={({ item, index }) => (
<View>
<TouchableOpacity
style={[styles.childRow, styles.button]}
onPress={() => onClick(index)}
>
<MaterialIcons
size={24}
name={item.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
<Text style={[styles.itemInActive]}>{item.key}</Text>
</TouchableOpacity>
<View style={styles.childHr} />
</View>
)}
/>
)}
</View>
);

If it does not work, I think you should create a component and use map datalist to render all the items and putting them into the ScrollView tag.
<ScrollView
style={styles.messageContain}
ref={ref => {
this.scrollView = ref;
}}
{data.data.map((item, index) => {
return <YourComponent key={index} data={item} />;
})}
</ScrollView>

Related

The menu is collapsing out but not in?

Im using the accordion-collapse-react-native library. What I have to do is, when the card is clicked and the menu is opened the arrow icon should change from arrow down to arrow up. The logic that im using is opening and changing the arrow but its not closing anymore. Can u help me to figure out why??
const [collapse, setCollapse] = useState(false);
<Collapse
style={styles.locationContainer}
isCollapsed={collapse}
onToggle={(isCollapsed) => setCollapse({ collapse: isCollapsed })}>
<CollapseHeader>
<TouchableOpacity onPress={() => setCollapse({ collapse: !collapse })}>
<Text style={styles.title}>Zgjedhni lokacionin</Text>
<View style={styles.friendsContainer}>
<View style={styles.itemsContainerLocation}>
<Text style={styles.subTitle}>Shtëpia e shokut</Text>
<Text style={styles.default}>(parazgjedhur)</Text>
</View>
{collapse ? (
<Ionicons name="ios-arrow-up" size={24} color="black" />
) : (
<Ionicons name="ios-arrow-down" size={20} color="black" />
)}
</View>
</TouchableOpacity>
</CollapseHeader>
<CollapseBody>
<View style={styles.adressesContainer}>
<Text style={styles.adressesName}>Shtëpia ime</Text>
</View>
<View style={styles.adressesContainer}>
<Text style={styles.adressesName}>Shtëpia e prindërve</Text>
</View>
<View style={styles.adressesContainer}>
<Text style={styles.adressesName}>Shtëpia e gjyshit</Text>
</View>
</CollapseBody>
</Collapse>
Your accordion-collapse-react-native component looks like the exemple in the doc (and this is not a reproach), the only difference is that you are using usestate hook and the exemple is a Class component so the managing state syntax change a bit.
Instead of onToggle={(isCollapsed) => setCollapse({ collapse: isCollapsed })}> try onToggle={(isCollapsed) => setCollapse( isCollapsed )}
And instead of <TouchableOpacity onPress={() => setCollapse({ collapse: !collapse })}> try <TouchableOpacity onPress={() => setCollapse( !collapse )}>

How can i set focus to only one TextInput in list item after TouchableOpacity pressed in this item?

I have a list of many items where each item has TextInput and TouchableOpacity wrapped by View.
I've trying to set focus on TextInput in the list item in which TouchableOpacity has been pressed. It's needed for editing each item's name.
Below is the code of how I tried to do this. The problem of this code is that after pressing on any of the TouchableOpacity the last TextInput will always be focused due to the fact that the last iteration overwrites textInputRef.
Is there a way to make textInputRef contain a reference to the TextInput which TouchableOpacity will press?
const ListComponent = ({list}) => {
const textInputValue = useRef('');
const textInputRef = useRef(null);
changeItemName = (text) => {
textInputValue.current = text;
};
return (
<ScrollView>
{list.length > 0 &&
list.map((item) => (
<View key={item._id}>
<TouchableOpacity>
<View
<Text>{`Item: `}</Text>
<TextInput ref={textInputRef} onChangeText={changeItemName}>
{item.name}
</TextInput>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
textInputValue.current = '';
}}>
<Icon name={'check'} size={25} color="#000" />
</TouchableOpacity>
<View>
<TouchableOpacity
onPress={() => {
textInputValue.current = item.name;
textInputRef.current.focus();
}}>
<Icon name={'edit'} size={25} color="#000" />
</TouchableOpacity>
</View>
</View>
))}
</ScrollView>
);
};
I think creating an array of ref will help you to resolve.
Try this way
const ListComponent = ({list}) => {
const textInputValue = useRef('');
const textInputRef = useRef(null);
changeItemName = (text) => {
textInputValue.current = text;
};
const collectionRef = useRef(list.map(() => createRef()));
return (
<ScrollView>
{list.length > 0 &&
list.map((item, index) => (
<View key={item._id}>
<TouchableOpacity>
<View
<Text>{`Item: `}</Text>
<TextInput ref={collectionRef.current[index]} onChangeText={changeItemName}>
{item.name}
</TextInput>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
textInputValue.current = '';
}}>
<Icon name={'check'} size={25} color="#000" />
</TouchableOpacity>
<View>
<TouchableOpacity
onPress={() => {
textInputValue.current = item.name;
collectionRef[index].current.focus();
}}>
<Icon name={'edit'} size={25} color="#000" />
</TouchableOpacity>
</View>
</View>
))}
</ScrollView>
);
};

can't submit a form when using FlatLists

Previously, I was rendering and mapping some data using another component called UserList. However, now I have changed it to a FlatList
When I was using {/* <UserList onSendRequest={onSendRequest} data={userData}></UserList> */}, every time I clicked on the button, the handleSubmit function was called successfully.
However, now I am using FlatList. Nothing happens when I click on the button. The handle submit does not run and I don't see anything from the flatList. What am I doing wrong?
return (
<SafeAreaView>
<View>
<View style={styles.searchTopContainer}>
<View style={styles.searchTopTextContainer}>
<Text>
Cancel
</Text>
</View>
<View>
<Formik
initialValues={initialValues}
onSubmit={handleSubmitForm}
validationSchema={validationSchema}>
{({ handleChange, handleBlur, handleSubmit, values }) => (
<View style={styles.searchFieldContainer}>
<View style={styles.form}>
<FieldInput
handleChange={handleChange}
handleBlur={handleBlur}
value={values.input}
fieldType="input"
icon="user"
placeholderText="Email or Phone Number or Name"
/>
<ErrorMessage
name="input"
render={(msg) => (
<Text style={styles.errorText}>{msg}</Text>
)}
/>
</View>
<View style={styles.buttonContainer}>
<Button
rounded
style={styles.searchButton}
onPress={handleSubmit}>
<Text style={styles.searchButtonText}>Search </Text>
</Button>
</View>
</View>
)}
</Formik>
</View>
{/* <UserList onSendRequest={onSendRequest} data={userData}></UserList> */}
{userData !== null &&
<FlatList
data={userData.users}
horizontal={false}
renderItem={({ item }) => (
<SingleUser
user={item}
onSendRequest={onSendRequest}
/>
)}
keyExtractor={(item) => item.id.toString()}
/>
}
</View>
</View>
</SafeAreaView>
);
};
UserList.tsx:
export const UserList: React.FunctionComponent<UserProps> = ({
data,
onSendRequest,
}) => {
if (!data) return null;
return (
<View style={styles.users}>
{data.users.nodes.map(
(item: { firstName: string; lastName: string; id: number }) => {
const userName = item.firstName.concat(' ').concat(item.lastName);
return (
<View style={styles.item} key={item.id}>
<Thumbnail
style={styles.thumbnail}
source={{
uri:
'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/afro_woman_female_person-512.png',
}}></Thumbnail>
<Text style={styles.userName}>{userName}</Text>
<View style={styles.addButtonContainer}>
<Button
rounded
style={styles.addButton}
onPress={() => onSendRequest(Number(item.id))}
>
<Icon name="plus" size={moderateScale(20)} color="black" />
</Button>
</View>
</View>
);
},
)}
</View>
);
};

How to navigate between different components based on conditions in react native

I am building a a mobile app in react native in which I have videos and audios coming in same data array. Now I am rendering them into a flatlist and audios and videos are coming together randomly. Now I want that If I click on the audio file it should navigate to Audios component and if I click on any video it should navigate to Videos Component. But I don't know how to filter and navigate to their respective components. Kindly help me. Thank you
My code
Main File: It is navigating to Audio component either I click on audio file or either on video file
<FlatList
horizontal
data={latestuploads}
keyExtractor={item => item.id}
renderItem={({item}) => {
return (
<ScrollView horizontal={true}>
<Card transparent style={{width: 170}}>
<TouchableOpacity
onPress={() =>
this.props.navigation.navigate('Audio', {id: item.id})
}>
<CardItem>
<ImageBackground
source={{uri: item.image_url}}
style={styles.image}>
<Image
source={require('../assets/play-icon.png')}
style={styles.icon}
/>
</ImageBackground>
</CardItem>
</TouchableOpacity>
<CardItem cardBody>
<Text numberOfLines={1} style={styles.title}>
{item.title}
</Text>
</CardItem>
<CardItem cardBody>
<Text style={styles.speaker}> {item.speaker} </Text>
</CardItem>
</Card>
</ScrollView>
);
}}
/>
I suppose you're getting file extension example .mp4/.mp3 etc or Audio/Video flag from your data array.
Create a function that takes file info example:
navigateTo = (fileinfo) => {
// const filetype = check for file type, Audio/Video or file extension
if (filetype === 'Audio'){
this.props.navigation.navigate('Audio', {id: fileinfo.id})
} else {
this.props.navigation.navigate('Video', {id: fileinfo.id})
}
Pass this to your TouchableOpacity:
<TouchableOpacity
onPress={() => navigateTo(item)}>
// your code here
</TouchableOpacity>
constructor()
{
super(props)
this.state = {
ItemindexChecked: "",
}
this.Dataarrayholder = latestuploads;
}
............................your code ............
DataFilter(p_value)
{
const newData = this.Dataarrayholder.filter(function (item) {
const itemData = item.value ? item.value.toUpperCase() : ''.toUpperCase();
const textData = p_value.toUpperCase();
return itemData.indexOf(textData) > -1;
if (p_value != "")
{
if (newData == 0) {
return
}
else
{
this.props.navigation.navigate('Audio', { id: newData[0].id });
}
}
});
}
...........................................your code ..............
<FlatList
horizontal
data={latestuploads}
keyExtractor={item => item.id}
renderItem={({ item }) => {
return (
<ScrollView horizontal={true}>
<Card transparent style={{ width: 170 }}>
<TouchableOpacity
//onPress={() =>
// // this.props.navigation.navigate('Audio', { id: item.id })
// }
onPress={() => { this.DataFilter(item.value), this.setState({ ItemindexChecked: item.key }) }}
>
<CardItem>
<ImageBackground
source={{ uri: item.image_url }}
style={styles.image}>
<Image
source={require('../assets/play-icon.png')}
style={styles.icon}
/>
</ImageBackground>
</CardItem>
</TouchableOpacity>
<CardItem cardBody>
<Text numberOfLines={1} style={styles.title}>
{item.title}
</Text>
</CardItem>
<CardItem cardBody>
<Text style={styles.speaker}> {item.speaker} </Text>
</CardItem>
</Card>
</ScrollView>
);
}}
/>
maybe it helpful for you

scrollview insde flatlist not scrolling

i have this flatlist in render():
render() {
return (
<FlatList
ref='listRef'
data={this.props.data}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
/>
)
}
Then inside renderItem() i have:
return (
<View style={{flex:1}}>
<ScrollView style={{flex:1}}>
{item.mascotas.map(function(d, index){
return (
<View key={index} style={{flex:1}}>
<Image source={require('./img/base-face-image.png')} style={styles.mascotas_list_item_img} />
<View style={styles.mascotas_list_item_details}>
<Text style={styles.mascotas_list_item_details_name}>{d.nombre}</Text>
</View>
</View>
)
})}
</ScrollView>
</View>
As you can see the parent view and its childs have flex:1, i've also tried adding flex:1 to FlatList but doesn't work neither. I need the scrollview to scroll.

Categories

Resources