How to access specific index of FlatList in react native - react-native

I am populating a FlatGrid from API. Each grid has an icon which is by default green color. I want to change the color of a specific icon when pressed. But as of now after pressing the icon, the color of all the icons are changing. Can anyone suggest what needs to be done? Attaching the code for reference. After pressing the icon green color should turn into blue.
constructor(props){
super(props);
this.state={
isLoading: true,
dataSource: null,
color:'green'
}
}
colorChange(color)
{
if(color=='green')
{
this.setState({
color:'blue'
})
}
else
{
this.setState({
color:'green'
})
}
}
render(){
if(this.state.isLoading){
return (
<View style={styles.container}>
<ActivityIndicator size="large" />
</View>
)
}else{
console.log(this.state.dataSource)
return(
<ScrollView>
<FlatGrid
itemDimension={130}
items={this.state.dataSource}
style={styles.gridView}
renderItem={({ item, index }) => (
<View style={{borderWidth:1,borderStyle:'dashed',borderRadius:1,width:120,height:50,flexDirection:'row'}}>
<Text style={{fontSize:20,paddingLeft:10}}>{item.Name}</Text>
<Icon
name="car"
size={30}
key={item.Name}
style={{color:(item.Status=='Available'?this.state.color:'grey'),paddingLeft:20,backgroundColor:'white'}}
onPress={this.colorChange.bind(this.state.color)}
/>
</View>
)}
keyExtractor={item => item.Name}
/>
</View>

You can do an array of colors but that's not a good practice.
The other solution is to handle the renderItem as a functional component since that's how it works.
Like this
renderItem={({ item, index }) => {
const [color, setColor] = React.useState('green')
return(
<View style={{borderWidth:1,borderStyle:'dashed',borderRadius:1,width:120,height:50,flexDirection:'row'}}>
<Text style={{fontSize:20,paddingLeft:10}}>{item.Name}</Text>
<Icon
name="car"
size={30}
key={item.Name}
style={{color:(item.Status=='Available'?color:'grey'),paddingLeft:20,backgroundColor:'white'}}
onPress={() => setColor('blue')}
/>
</View>
)}}

Related

How to place a footer element in a FlatList in a row. React-Native

I have FlatList with 2 colums, and i want place FooterElement in row
export const HabitScreen = ({navigation}) => {
return (
<View style={{marginTop: 40}}>
<MyPlansTitle navigation={navigation}/>
<GeneralView>
<SubTitle text="Привычки"/>
<FlatList data={[0,1,2]}
extraData={[3]}
numColumns={2}
columnWrapperStyle={style.row}
showsVerticalScrollIndicator={false}
renderItem={({item}) => (<HabitItem/>)}
ListFooterComponent={<HabitAddItem />}
/>
</GeneralView>
</View>
)}
how to do it?
Image Flatlist
add one more element to the data,
renderItem={({item, index}) => {
if (index+1 == data.length){
return <Text>Footer</Text>
}
return <Text>{item}</Text>
}}

How to Send data from from one components flat-list to another component in react native

Categories.js
<FlatList
data={categorylist}
keyExtractor={(item, index) => item.tc_id}
vertical
numColumns={4}
renderItem={({ item, index }) => {
return (
<Pressable onPress={subcat}>
<View style={styles.catLayout}>
<View style={styles.imageLayout}>
<Image source={{ uri: item.image }} style={styles.image}
/>
</View>
<Text style={styles.productname}>
{item.name != null ? item.name : ""}
</Text>
<Text>{item.uuid}</Text>
</View>
</Pressable>
);
}}
/>
I am getting data from categorylist array , i am displaying a bunch of items of categories here , i want show different sub-categories depending on each items "uuid".
I want to send the {item.uuid} to subcategories screen and reuse it in there.
As you are displaying the data on the view using flatlist you have onPress after clicking on any item you just need to send the data
Screen (A)
<FlatList
data={categorylist}
keyExtractor={(item, index) => item.tc_id}
vertical
numColumns={4}
renderItem={({ item, index }) => {
return (
<Pressable onPress={() => navigation.navigate('subcategories',{uuid:item.uuid}) }>
<View style={styles.catLayout}>
<View style={styles.imageLayout}>
<Image source={{ uri: item.image }} style={styles.image}
/>
</View>
<Text style={styles.productname}>
{item.name != null ? item.name : ""}
</Text>
<Text>{item.uuid}</Text>
</View>
</Pressable>
);
}}
/>
Screen (B)
you can get it like this
class component
constructor(props) {
super(props);
this.state = {
uuID: this.props.navigation.state.params.uuid,
}
}
functional component
const Subcategory = (props) => {
const [uUID, setuUID] = useState(props.route.params.uuid);

I am not able to navigate to the other screen in my react native project the error is: navigation not found

const Item = ({ item }) => (
<TouchableOpacity
onPress={() => this.navigation.navigate(
"carProfile",
{item: item}
)}>
<View style={styles.item}>
<Text style={styles.title}>{item.name}</Text>
<Text style={styles.details}>{item.details}</Text>
</View>
</TouchableOpacity>
);
const List = (props,navigation) => {
const renderItem = ({ item }) => {
if (props.searchPhrase === "") {
return <Item item={item} />;
}
if (item.name.toUpperCase().includes(props.searchPhrase.toUpperCase().trim().replace(/\s/g, ""))) {
return <Item item={item} />;
}
if (item.details.toUpperCase().includes(props.searchPhrase.toUpperCase().trim().replace(/\s/g, ""))) {
return <Item item={item} />;
}
};
return (
<SafeAreaView style={styles.list__container}>
<View
onStartShouldSetResponder={() => {
props.setClicked(false);
}}
>
<FlatList
data={props.data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</View>
</SafeAreaView>
);
};
export default List;
the error is continuing to be there despite me trying to put navigation container in different positions. I want to send the user to the carProfile page, where the data passed in item is reused. This way user can know about the selection they are looking for
Use this way
onPress={() => this.props.navigation.navigate(
"carProfile",
{item: item}
)}
The navigation is inside the props, not as a second argument. Below is a classic example. And also note, you cannot extract navigation prop for child components, it will only work on Main components(Screens).
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
If you want to use navigation inside child components, you can use the navigation hooks.
import { useNavigation } from "#react-navigation/native";
function MyBackButton() {
const navigation = useNavigation();
return (
<Button
title="Back"
onPress={() => {
navigation.goBack();
}}
/>
);
}

React-Native modal not showing FlatList Items

Modal only displays button but not FlatList item.
I am trying to build a custom app picker for my react-native-app which renders a list of items on a modal.
AppPicker.js
const AppPicker = ({ icon, items, placeholder }) => {
const [modalVisible, setModalVisible] = React.useState(false)
return (
<>
<TouchableWithoutFeedback onPress={() => setModalVisible(true)} >
<View style={styles.container}>
{icon && <MaterialCommunityIcons name={icon} size={20} style={styles.icon} />}
<AppText style={styles.text}> {placeholder} </AppText>
<MaterialCommunityIcons name="chevron-down" size={20} />
</View>
</TouchableWithoutFeedback>
<Modal visible={modalVisible} animationType="slide" >
<Button title="Close" onPress={() => setModalVisible(false)} />
<FlatList
data={items}
keyExtractor={item => item.value.toString()}
renderItem={({ item }) =>
<PickerItem
lable={item.label}
onPress={() => console.log(item)}
/>}
/>
</Modal>
</>
)
}
the <PickerItem/> that should be rendered by the flatlist is a component that just displays the items from the list.
PickerItem.js
const PickerItem = ({ label, onPress }) => {
return (
<TouchableOpacity onPress={onPress}>
<AppText> {label} </AppText>
</TouchableOpacity>
)
}
export default PickerItem;
when I randomly tap on the modal screen however the onPress() on the FlatList triggers the console.log(item) and the items are displayed on the console. Any help on this will be appreciated.
** App.js **
const categories = [
{ label: "furniture", value: 1 },
{ label: "clothing", value: 2 },
{ label: "phone", value: 3 },
]
export default function App() {
return (
<Screen style={styles.container}>
<AppPicker items={categories} icon="apps" placeholder="category" />
<AppTextInput icon="email" placeholder="email" />
</Screen>
);
}
NOTE: I am using expo to run the application.

React Native Flatlist with radio buttons works slow

I have flatlist with custom radio buttons implementaion, but when i tap on flatlist item it waits about second before changes to active button. I tried to useCallback with my renderItem and itemKeyExtractor functions but it doesnt help me.
Here is the code of my screen component:
export const PickOrganizationScreen = (props) => {
const { navigation, setOrganization, loadProcedureProviders, items, isLoading, procedureId, organizationId } = props;
useFocusEffect(
React.useCallback(()=>{loadProcedureProviders(procedureId);},[loadProcedureProviders, procedureId])
);
const renderItem = ({item}) => {
return (
<OrganizationItem
title={item.Title}
checked = {item.Id === organizationId}
onPress={() => {
setOrganization(item.Id, item.Title);
}}
/>);
};
const itemKeyExtractor = (item) => item.Id;
return (
isLoading ? (
<Spinner />
) : (
items.length > 0 ? (
<View style={styles.container}>
<View style={styles.paragraph}>
<Text style={styles.subtitle}>{I18n.t('pickOrganization')}</Text>
</View>
<View style={styles.alertMessage}>
<View style={styles.alertIcon}>
<Icon name="info" width={32} height={32} fill={Colors.primaryRed} />
</View>
<View>
<Text style={styles.alertText}>{I18n.t('pickOrganizationToRegisterService')}</Text>
</View>
</View>
<FlatList
data = {items}
renderItem = {renderItem}
keyExtractor = {itemKeyExtractor}
extraData={organizationId}
/>
<View style={styles.buttonWrapper}>
<ScreenButton
title={I18n.t('goToRegister')}
onPress={ () => {
navigation.navigate('ServiceSummary');
}}/>
</View>
</View>
) : (
<NotFound extraText={I18n.t('notFoundExtra')}/>
)
)
);
};
Here is the code of flatlist item component:
export const OrganizationItem = ({title, checked, onPress}) => {
return (
<TouchableOpacity onPress={onPress}>
<View style={styles.itemContainer}>
<View style={styles.itemIcon}>
{ checked ? (
<Icon name="radio-button-on" width={16} height={16} fill={Colors.primaryRed} />
) :
(
<Icon name="radio-button-off" width={16} height={16} fill={Colors.gray} />
)
}
</View>
<View style={styles.itemText}>
<Text style={styles.title}>{title}</Text>
</View>
</View>
</TouchableOpacity>
);
};
Try memoizing OrganizationItem. Does the onPress in OrganizationItem change the items object ? If so, it will re-render the whole Flatlist even when one small change is made. If you memoize, the components memoized won't rerender unless the props passed to it changes.
export const OrganizationItem = React.memo(({title, checked, onPress}) => {
return (
<TouchableOpacity onPress={onPress}>
<View style={styles.itemContainer}>
<View style={styles.itemIcon}>
{ checked ? (
<Icon name="radio-button-on" width={16} height={16} fill={Colors.primaryRed} />
) :
(
<Icon name="radio-button-off" width={16} height={16} fill={Colors.gray} />
)
}
</View>
<View style={styles.itemText}>
<Text style={styles.title}>{title}</Text>
</View>
</View>
</TouchableOpacity>
);
});