Searchable flat list react native - react-native

I am trying to search items in a flatlist, whenever i type in the search bar it only take one letter and closes the keyboard and the value inside the search bar disappear,
example when i type "george" it only takes the letter g and re-render a list of names containing the letter g and delete what's inside the search bar
how can i fix this ?
import React, { useState, useEffect } from 'react';
import { ScrollView } from 'react-native';
import { View, Text, FlatList, ActivityIndicator, SafeAreaView, TouchableOpacity } from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Divider, SearchBar } from 'react-native-elements'
const Item = ({ name, lastName }) => (
<View>
<Text style={{ fontSize: 17, color: '#666', marginBottom: 10 }}>Full name: {name} {lastName}</Text>
</View>);
function Clients({ navigation }) {
const [isLoading, setLoading] = useState(true);
const usersApi = 'https://reqres.in/api/users'
const [users, setUsers] = useState([]);
const [search, setSearch] = useState("");
const [masterData, setMasterData] = useState("");
const fetchJson = async (userApi) => {
const response = await fetch(userApi);
return response.json()
}
useEffect(() => {
fetchJson(usersApi)
.then((users) => {
setUsers(users.data);
setMasterData(users.data);
})
.catch((error) => (alert(error)))
.finally(() => setLoading(false));
}, []);
const itemSeparator = () => {
return (
<Divider style={{ width: "105%", marginVertical: 3, alignSelf: 'center' }} />
)
}
const renderHeader = () => {
return (
<SearchBar
placeholder="Type Here..."
lightTheme
round
onChangeText={text => searchFilterFunction(text)}
autoCorrect={false}
/>
);
};
const searchFilterFunction = text => {
setSearch(text);
const newData = masterData.filter(item => {
const itemData = `${item.first_name.toUpperCase()} ${item.last_name.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
setUsers(newData);
};
const renderItem = ({ item }) => (
<TouchableOpacity style={{
flex: 1,
padding: 10
}}
onPress={() => { navigation.navigate('Client', { item: item }); }}
underlayColor='#ccc'
activeOpacity={0.1} >
<Item name={item.first_name} lastName={item.last_name} />
</TouchableOpacity>
);
console.log(search)
console.log(users)
return (
<SafeAreaProvider>
<SafeAreaView>
<Text style={{ color: '#666', margin: 15, fontSize: 20 }}>Clients actuels</Text>
<View style={{
width: '96%',
backgroundColor: 'white',
borderRadius: 5,
alignSelf: 'center',
marginTop: 20,
}}>
<View style={{ margin: 15 }}>
{isLoading ? <ActivityIndicator size="large" /> :
<FlatList
data={users}
renderItem={renderItem}
ItemSeparatorComponent={itemSeparator}
ListHeaderComponent={renderHeader}
keyExtractor={item => item.id.toString()}
value={search}
/>}
</View>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
export default Clients;

Related

Lodesh Filter is giving mid string data

I am new with React Native and facing issue with Lodesh Filter. It is giving mid-string data. Ex if I want to search Mitsubishi and start typing "mi" it will not give me mitsubishi but if I start type "sub" then it is giving me mitsubishi.
Below is my code:
import React, { useEffect, useState } from 'react';
import {View, Text, Button, TextInput, FlatList, ActivityIndicator, StyleSheet, Image} from 'react-native';
import filter from 'lodash.filter';
const CarList = () => {
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState([]);
const [error, setError] = useState(null);
const [query, setQuery] = useState('');
const [fullData, setFullData] = useState([]);
useEffect(() => {
setIsLoading(true);
fetch(`https://myfakeapi.com/api/cars/?seed=1&page=1&results=20`)
.then(response => response.json())
.then(response => {
setData(response.cars);
setFullData(response.cars);
setIsLoading(false);
})
.catch(err => {
setIsLoading(false);
setError(err);
});
}, []);
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#5500dc" />
</View>
);
}
if (error) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontSize: 18}}>
Error fetching data... Check your network connection!
</Text>
</View>
);
}
const handleSearch = text => {
const formattedQuery = text.toLowerCase();
const filteredData = filter(fullData, user => {
console.log(contains(user, formattedQuery));
return contains(user, formattedQuery);
});
setData(filteredData);
setQuery(text);
};
const contains = ({ car, car_model,car_color }, query) => {
if (car.includes(query) || car_model.includes(query) || car_color.includes(query)) {
return true;
}
return false;
};
function renderHeader() {
return (
<View
style={{
backgroundColor: '#fff',
padding: 10,
marginVertical: 10,
borderRadius: 20
}}
>
<TextInput
autoCapitalize="none"
autoCorrect={false}
clearButtonMode="always"
value={query}
onChangeText={queryText => handleSearch(queryText)}
placeholder="Search"
style={{ backgroundColor: '#fff', paddingHorizontal: 20 }}
/>
</View>
);
}
return (
<View style={styles.container}>
<Text style={styles.text}>Favorite Contacts</Text>
<FlatList
ListHeaderComponent={renderHeader}
data={data}
keyExtractor={({ id }) => id}
renderItem={({ item }) => (
<View style={styles.listItem}>
<Image
source={{
uri: 'https://picsum.photos/200',
}}
style={styles.coverImage}
/>
<View style={styles.metaInfo}>
<Text style={styles.title}>{`${item.car} ${
item.car_model
}`}</Text>
</View>
</View>
)}
/>
</View>
);
}
Each car record have following fields:
{
"id": 1,
"car": "Mitsubishi",
"car_model": "Montero",
"car_color": "Yellow",
"car_model_year": 2002,
"car_vin": "SAJWJ0FF3F8321657",
"price": "$2814.46",
"availability": false
}
When you write mit, in contain function you are checking if(car.includes(text)...) but car name starts with an uppercase letter. You need to convert the car name in lowerCase before checking the text like this:
const contains = ({ car, car_model, car_color }, query) => {
if (car.toLowerCase().includes(query) || car_model.toLowerCase().includes(query) || car_color.toLowerCase().includes(query)) {
return true;
}
return false;
};

How to put the bottomsheet to the front of the screen?

In ReactNative, the bottomsheet is displayed overlaid on the fragment.
Is there a way to make the bottomsheet rise to the top of the screenenter image description here
The bottom sheet looks opaque as in the picture, so the bottom sheet cannot be touched Please help
The code below is a shortened version
enter image description here
enter image description here
import React, { FC , Component, useState, useEffect, Fragment,useCallback, useMemo, useRef } from "react"
import { FlatList, ViewStyle, StyleSheet, View, Platform, TextInput, TouchableOpacity} from "react-native"
import {
BottomSheetModal,
BottomSheetModalProvider,
BottomSheetBackdrop,
} from '#gorhom/bottom-sheet';
const ROOT: ViewStyle = {
backgroundColor: DefaultTheme.colors.background,
flex: 1,
}
export const ChecklookupScreen: FC<StackScreenProps<NavigatorParamList, "checklookup">> = observer(function ChecklookupScreen() {
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
// variables
const snapPoints = useMemo(() => ['25%', '50%'], []);
// callbacks
const handlePresentModalPress = useCallback((index: string) => {
LOG.info('handlePresentModalPress', index);
bottomSheetModalRef.current?.present();
}, []);
const handleSheetChanges = useCallback((index: number) => {
LOG.info
console.log('handleSheetChanges', index);
}, []);
const renderItem = ({ item, index }) => (
<TouchableOpacity
key={index + item.inspNo + item.spvsNo}
//style={listContainer}
onPress={throttle(() => {
onClickItem(item.inspNo,item.spvsNo);
})}
>
<View>
<Fragment>
</View>
<Button icon="magnify-expand"
mode="elevated"
style={styles.detailButton}
onPress={throttle(() => {
onClickItem(item.inspNo,item.spvsNo);
})}
// onPress={() => navigation.navigate("checkdetail")}
>
</Button>
</View>
</Fragment>
</View>
</TouchableOpacity>
);
const fetchChecklookups = async (offset: number) => {
LOG.debug('fetchChecklookups:' + offset);
setRefreshing(true);
await checklookupStore.getChecklookups(offset)
setRefreshing(false);
};
const onEndReached = () => {
if (checklookupStore?.checklookupsTotalRecord <= checklookups?.length) {
LOG.debug('onEndReached555555555');
} else {
setPage(page + 1)
fetchChecklookups(page + 1);
}
};
const [searchQuery, setSearchQuery] = React.useState('');
const onChangeSearch = query => setSearchQuery(query);
return (
<Screen preset="fixed" style={{ backgroundColor: colors.background, flex: 1, padding: 10,}}>
<View style={{ flex: 1,}}>
<View style={{ flex: 1, }}>
<Searchbar
placeholder="조회조건을 입력해주세요"
onChangeText={onChangeSearch}
value={searchQuery}
onPressIn={() => handlePresentModalPress('touch on')}
/>
<BottomSheetModalProvider>
<BottomSheetModal
backgroundStyle={{ backgroundColor: "gray" }}
style={styles.bottomSheet}
ref={bottomSheetModalRef}
index={1}
snapPoints={snapPoints}
onChange={handleSheetChanges}
>
<View style={{ marginTop: 10, marginLeft: 50, marginRight: 50, flexDirection: "row"}}>
<View style={{ flex: 1, }}>
<Button
mode="outlined"
>소속을 입력하세요
</Button>
</View>
</View>
</BottomSheetModal>
</BottomSheetModalProvider>
</Screen>
)
})
You can try with portal, wrap you bottom sheet to from another package.

Nested lists - How to modify (delete, add, update) items from a nested list using item's buttons and useState?

My first idea was to try to delete items from a nested list. I've started using SectionList and a component that has an useState that manages the data changes of the SectionList. I'm trying to solve it using SectionList but it'd be great to display all possible alternatives (FlatList, ViewList, etc).
I figured out how to delete a whole section list (and his items) but not one item by one. I've read plenty of posts, but I did find nothing related to managing SectionList items. Maybe there's an answer out there for FlatList nested items.
Here I left an example code ready to use (without styles) based on React Native official docs:
import React, { useEffect } from "react";
import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar, Button } from "react-native";
import { useState } from "react";
const dataResource = [
{
title: "Main dishes",
data: ["Pizza", "Burger", "Risotto"],
n: "delete",
k: 1
},
{
title: "Sides",
data: ["French Fries", "Onion Rings", "Fried Shrimps"],
n: "delete",
k: 2
},
];
function App() {
const [state, setState] = useState(dataResource)
const Item = ({ dish, obj, i}) => (
<View >
<Text >{dish} </Text>
<Button title={obj.n} onPress={() => {}} /> // add the handler
</View>
);
const SectionComponent = ({ t, k }) => (
<View>
<Text >{t} </Text>
<Button title={'section'} onPress={() => { setState(state.filter(e => e.k != k)) }} />
</View>
);
return (
<SafeAreaView >
<SectionList
sections={state}
keyExtractor={(item, index) => item + index}
renderItem={({ item, section, index}) => <Item dish={item} obj={section} i={index}/>}
renderSectionHeader={({ section: { title, k } }) => <SectionComponent k={k} t={title} />}
/>
</SafeAreaView>
);
}
export default App;
I think how you display the data is trivial. The component you use will just change how you access the data, not how you update it. What you need is helper functions for editing the data. With those in place you can do things like add/remove section items, and editing section items themselves:
import React, { useState } from 'react';
import {
Text,
View,
StyleSheet,
SafeAreaView,
SectionList,
Button,
TextInput,
} from 'react-native';
const dataResource = [
{
title: 'Main dishes',
data: ['Pizza', 'Burger', 'Risotto'],
id: 1,
},
{
title: 'Sides',
data: ['French Fries', 'Onion Rings', 'Fried Shrimps'],
id: 2,
},
];
export default function App() {
const [state, setState] = useState(dataResource);
const [sectionTitle,setSectionTitle] = useState('Drinks')
const editItem = (itemId, newValue) => {
let newState = [...state];
let itemIndex = newState.findIndex((item) => item.id == itemId);
if (itemIndex < 0) return;
newState[itemIndex] = {
...newState[itemIndex],
...newValue,
};
setState(newState);
};
const addSectionItem = (title)=>{
let newState = [...state]
newState.push({
title,
data:[],
id:newState.length+1
})
setState(newState)
}
const removeFood = (itemId, food) => {
let currentItem = state.find((item) => item.id == itemId);
console.log(currentItem);
currentItem.data = currentItem.data.filter((item) => item != food);
console.log(currentItem.data);
editItem(itemId, currentItem);
};
const addFood = (itemId, food) => {
let currentItem = state.find((item) => item.id == itemId);
console.log(currentItem.data);
currentItem.data.push(food);
console.log(currentItem.data);
editItem(itemId, currentItem);
};
const Item = ({ item, section, index }) => {
return (
<View style={styles.row}>
<Text>{item} </Text>
<Button
title={'Delete'}
onPress={() => {
removeFood(section.id, item);
}}
/>
</View>
);
};
const SectionHeader = ({ title, id }) => {
return (
<View style={styles.header}>
<Text style={{ fontSize: 18 }}>{title} </Text>
<Button
title={'X'}
onPress={() => {
setState(state.filter((e) => e.id != id));
}}
/>
</View>
);
};
const SectionFooter = ({ id }) => {
const [text, setText] = useState('');
return (
<View style={[styles.row, styles.inputWrapper]}>
<Text>Add Entry</Text>
<TextInput
value={text}
onChangeText={setText}
style={{ borderBottomWidth: 1 }}
/>
<Button title="Add" onPress={() => addFood(id, text)} />
</View>
);
};
return (
<SafeAreaView>
<Button title="Reset list" onPress={() => setState(dataResource)} />
<View style={[styles.row, styles.inputWrapper]}>
<Text>Add New Section</Text>
<TextInput
value={sectionTitle}
onChangeText={setSectionTitle}
style={{ borderBottomWidth: 1 }}
/>
<Button title="Add" onPress={() => addSectionItem(sectionTitle)} />
</View>
<View style={styles.sectionListWrapper}>
<SectionList
sections={state}
keyExtractor={(item, index) => item + index}
renderItem={Item}
renderSectionHeader={({ section }) => <SectionHeader {...section} />}
renderSectionFooter={({ section }) => <SectionFooter {...section} />}
/>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
padding: 5,
alignItems: 'center',
},
header: {
flexDirection: 'row',
paddingVertical: 5,
width: '100%',
borderBottomWidth: 1,
},
inputWrapper: {
paddingVertical: 15,
marginBottom: 10,
},
sectionListWrapper: {
padding: 5,
},
});
Here's a demo
I've improved my answer to give a clearer example of how to manipulate SectionList. An example of how to add/delete/modify sections and its data is provided.
import React from 'react';
export default function useStateHelpers(state, setState) {
const editSection = (sectionId, newValue) => {
// parse and stringify is used to clone properly
let newState = JSON.parse(JSON.stringify(state));
let itemIndex = newState.findIndex((item) => item.id == sectionId);
if (itemIndex < 0) return;
const section = {
...newState[itemIndex],
...newValue,
};
newState[itemIndex] = section;
setState(newState);
};
const editSectionDataItem = (sectionId, itemId, newValue) => {
const newState = JSON.parse(JSON.stringify(state));
const sectionIndex = newState.findIndex(
(section) => section.id == sectionId
);
const section = newState[sectionIndex];
const itemIndex = section.data.findIndex((item) => item.id == itemId);
let item = section.data[itemIndex];
section.data[itemIndex] = {
...item,
...newValue,
};
editSection(sectionId, section);
};
const editSectionTitle = (sectionId, title) =>
editSection(sectionId, { title });
const setSelectSectionItem = (sectionId, itemId, isSelected) => {
editSectionDataItem(sectionId, itemId, { isSelected });
};
const removeSectionDataItem = (sectionId, food) => {
let newState = JSON.parse(JSON.stringify(state));
let sectionIndex = newState.findIndex((section) => section.id == sectionId);
let section = newState[sectionIndex];
section.data = section.data.filter((item) => item.title != food);
editSection(sectionId, section);
};
const addSectionDataItem = (sectionId, title, price) => {
let newState = JSON.parse(JSON.stringify(state));
let sectionIndex = newState.findIndex((section) => section.id == sectionId);
let section = newState[sectionIndex];
section.data.push({
title,
price,
id: `section-${sectionId}-${section.data.length + 1}`,
});
editSection(sectionId, section);
};
const addSection = (title, data = [], id) => {
let newState = JSON.parse(JSON.stringify(state));
newState.push({
title,
data,
id: newState.length + 1,
});
setState(newState);
};
const helpers = {
editSection,
editSectionTitle,
removeSectionDataItem,
addSectionDataItem,
addSection,
setSelectSectionItem,
editSectionDataItem,
};
return helpers;
}
import React, { useState } from 'react';
import {
StyleSheet,
SafeAreaView,
View,
Button,
SectionList,
} from 'react-native';
import data from './data';
import StateContext from './StateContext';
import useStateHelpers from './hooks/useStateHelpers';
import Header from './components/SectionHeader';
import Footer from './components/SectionFooter';
import Item from './components/SectionItem';
import TextInput from './components/Input';
export default function App() {
const [state, setState] = useState(data);
const [sectionTitle, setSectionTitle] = useState('');
const helpers = useStateHelpers(state, setState);
return (
<SafeAreaView style={{ flex: 1 }}>
<StateContext.Provider value={{ state, setState, ...helpers }}>
<View style={styles.container}>
<Button title="Reset list" onPress={()=>setState(data)} />
<TextInput
label={'Add New Section'}
value={sectionTitle}
onChangeText={setSectionTitle}
onRightIconPress={() => {
helpers.addSection(sectionTitle);
setSectionTitle('');
}}
/>
<View style={styles.sectionListWrapper}>
<SectionList
style={{ flex: 1 }}
sections={state}
renderItem={(props) => <Item {...props} />}
renderSectionHeader={(props) => <Header {...props} />}
renderSectionFooter={(props) => <Footer {...props} />}
/>
</View>
</View>
</StateContext.Provider>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 8,
},
sectionListWrapper: {
padding: 5,
flex: 1,
},
});
import React, { useContext } from 'react';
import { View, TouchableOpacity, StyleSheet, Text, Button } from 'react-native';
import StateContext from '../StateContext';
export default function Item({ item, section, index }) {
const {
removeSectionDataItem,
setSelectSectionItem
} = useContext(StateContext);
const hasPrice = item.price.toString().trim().length > 0;
return (
<TouchableOpacity
style={[styles.container, item.isSelected && styles.selectedContainer]}
onPress={() =>
setSelectSectionItem(section.id, item.id, !item.isSelected)
}
>
<View style={styles.row}>
<Text>
{item.title + (hasPrice ? ' | ' : '')}
{hasPrice && <Text style={{ fontWeight: '300' }}>{item.price}</Text>}
</Text>
<Button
title={'Delete'}
onPress={() => {
removeSectionDataItem(section.id, item.title);
}}
/>
</View>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
container: {
marginVertical: 2,
},
selectedContainer: {
backgroundColor: 'rgba(0,0,0,0.2)',
},
row: {
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
padding: 5,
alignItems: 'center',
},
});
/*SectionFooter.js*/
import React, { useState, useContext, useEffect } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import TextInput from './Input';
import StateContext from '../StateContext';
export default function SectionFooter({ section }) {
const [title, setTitle] = useState('');
const [price, setPrice] = useState('');
const [titleWasEdited, setTitleWasEdited] = useState(false);
const { addSectionDataItem, editSectionDataItem } = useContext(StateContext);
const selectedItem = section.data.find((item) => item.isSelected);
// listen for item selection
useEffect(() => {
// pass item values to text input
setTitle(selectedItem?.title || '');
setPrice(selectedItem?.price || '');
// reset title/price input
setTitleWasEdited(false);
}, [selectedItem]);
return (
<View style={styles.container}>
<Text>
{selectedItem
? 'Editing ' + selectedItem.title
: 'Add New Entry'
}
</Text>
{/*one input handles both title and price*/}
<TextInput
label={titleWasEdited ? 'Price' : 'Title'}
value={titleWasEdited ? price : title}
onChangeText={titleWasEdited ? setPrice : setTitle}
rightIconName={titleWasEdited ? 'plus' : 'arrow-right'}
// rightIcon is disabled when theres no text
// but price is allowed to be empty
allowEmptySubmissions={titleWasEdited}
style={{ width: '80%' }}
onRightIconPress={() => {
// after title is edited allow submission
if (titleWasEdited) {
// if item was edited update it
if (selectedItem) {
editSectionDataItem(section.id, selectedItem.id, {
title,
price,
isSelected: false,
});
}
// or add new item
else {
addSectionDataItem(section.id, title, price);
}
setTitle('');
setPrice('');
}
// toggle between title & price
setTitleWasEdited((prev) => !prev);
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
marginVertical: 20,
alignItems: 'center',
},
});
import React, { useContext } from 'react';
import { View, StyleSheet } from 'react-native';
import { TextInput } from 'react-native-paper';
import StateContext from '../StateContext';
export default function SectionHeader({ section: { id, title } }) {
const { editTitle, setState, state } = useContext(StateContext);
return (
<View style={{ borderBottomWidth: 1 }}>
<View style={styles.header}>
<TextInput
style={styles.titleInput}
value={title}
onChangeText={(text) => {
editTitle(id, text);
}}
right={
<TextInput.Icon
name="close"
onPress={() => {
setState(state.filter((sec) => sec.id != id));
}}
/>
}
underlineColor="transparent"
activeUnderlineColor="transparent"
outlineColor="transparent"
activeOutlineColor="transparent"
selectionColor="transparent"
dense
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
header: {
flexDirection: 'row',
width: '100%',
justifyContent: 'space-around',
alignItems: 'center',
},
titleInput: {
fontSize: 18,
backgroundColor: 'transparent',
borderWidth: 0,
borderColor: 'transparent',
height: 36,
},
});

Error in uploading image with 'react-native-image-picker' library

I am creating an android application and I need to use the react-native-image-picker library but it is showing some error, the error is:
[Unhandled promise rejection: TypeError: null is not an object (evaluating '_reactNative.NativeModules.ImagePickerManager.launchImageLibrary')]
I have tried everything like changing to different versions as well, also I have used expo-image-picker which does not show an error while fetching an image from android but gives an error when uploading it to firebase.
Please help, I have been frustrated with this error.
import {
View,
Text,
Image,
StyleSheet,
KeyboardAvoidingView,
TouchableOpacity,
ActivityIndicator
} from "react-native";
import React, { useState } from "react";
import { TextInput, Button } from "react-native-paper";
import ImagePicker, { launchImageLibrary } from "react-native-image-picker";
import storage from "#react-native-firebase/storage";
import auth from '#react-native-firebase/auth';
import firestore, {getStorage, ref, uploadBytes} from '#react-native-firebase/firestore';
export default function SignUp({ navigation }) {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [image, setImage] = useState(null);
const [shownext, setShownext] = useState(false);
const [loading, setLoading] = useState(false);
if (loading) {
return <ActivityIndicator size='large' />
}
const userSignUp = async () => {
setLoading(true)
if (!email || !password || !image || !name) {
alert('fill all details correctly')
return false;
}
try {
const result = await auth().createUserWithEmailAndPassword(email, password);
firestore().collection('users').doc(result.user.uid).set({
name: name,
email: result.user.email,
uid: result.user.uid,
pic:image
})
setLoading(false)
}catch (err) {
alert('something went wrong from your side')
}
}
const pickImageAndUpload = () => {
console.log(1);
launchImageLibrary({ puality: 0.5 }, async (fileobj) => {
console.log(2);
console.log(fileobj);
const uploadTask = storage().ref().child(`/userprofilepic/${Date.now()}`).putFile(fileobj.uri);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
if (progress == 100) alert("image uploaded");
},
(error) => {
alert("error uploading image");
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setImage(downloadURL);
});
}
);});
};
return (
<KeyboardAvoidingView behavior="position" style={{ alignItems: "center" }}>
<View style={styles.box1}>
<Text style={styles.text}>Welcome to chatapplication</Text>
<Image style={styles.img} source={require("../assets/wa-logo.png")} />
</View>
{!shownext && (
<>
<TextInput
style={{ width: 330, marginTop: 50, marginBottom: 30 }}
label="Email"
value={email}
mode="outlined"
onChangeText={(text) => setEmail(text)}
/>
<TextInput
style={{ width: 330, marginBottom: 30 }}
label="Password"
value={password}
mode="outlined"
onChangeText={(text) => setPassword(text)}
secureTextEntry
/>
</>
)}
{shownext ? (
<>
<TextInput
style={{ width: 330, marginTop: 50, marginBottom: 30 }}
label="Name"
value={name}
mode="outlined"
onChangeText={(text) => setName(text)}
/>
<Button
style={{ marginBottom: 30 }}
mode="contained"
onPress={() => { pickImageAndUpload() }}
>
Upload Profile Pic
</Button>
<Button
disabled={image?false:true}
mode="contained"
onPress={() => { userSignUp() }}>
SignUp
</Button>
</>
) : (
<Button
// disabled={email&&password?false:true}
mode="contained"
onPress={() => {
setShownext(true);
}}
>
Next
</Button>
)}
<TouchableOpacity onPress={() => navigation.goBack()}>
<Text style={{ margin: 10, textAlign: "center", fontSize: 18 }}>
Already have an account?
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
text: {
fontSize: 22,
color: "green",
margin: 20,
},
img: {
width: 200,
height: 200,
},
box1: {
alignItems: "center",
},
});

How do i pass the value in counter component to the add to the To Cart Button

Hi I have a add minus component button that I want to pass the value to selected value to the "To Cart" button. If the value is zero the orders will not be added but if the value is > 0 then it will be added to cart.
below is my Add Minus button component
AddMinusButton.js
import React, { useState } from "react";
import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
import Colors from "../../constants/Colors";
const AddMinusButton = () => {
const [value, setValue] = useState(0);
const minusValue = () => {
if (value > 0) {
setValue(value - 1);
} else {
setValue(0);
}
};
const plusValue = () => {
setValue(value + 1);
};
return (
<View style={styles.container}>
<TouchableOpacity style={styles.buttonLeft} onPress={minusValue}>
<Text>-</Text>
</TouchableOpacity>
<Text style={styles.quantity}> {value}</Text>
<TouchableOpacity style={styles.buttonRight} onPress={plusValue}>
<Text>+</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: "row",
alignItems: "center",
borderWidth: 1,
borderRadius: 10,
height: 35,
overflow: "hidden",
borderColor: "black",
},
quantity: {
paddingHorizontal: 10,
marginRight: 3,
},
buttonLeft: {
alignItems: "center",
backgroundColor: Colors.primary,
borderRightWidth: 1,
borderRightColor: "black",
padding: 10,
},
buttonRight: {
alignItems: "center",
backgroundColor: Colors.primary,
borderLeftWidth: 1,
borderLeftColor: "black",
padding: 10,
},
});
export default AddMinusButton;
This is my Product Screen. I want to pass the value that is selected by the AddMinusButton component to the "To Cart". I am only able to made the button click and it will add one by one.
ProductOverviewScreen.js
import React, { useState, useEffect, useCallback } from "react";
import {
View,
Text,
FlatList,
Button,
Platform,
ActivityIndicator,
StyleSheet,
} from "react-native";
import { useSelector, useDispatch } from "react-redux";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../../components/UI/HeaderButton";
import ProductItem from "../../components/shop/ProductItem";
import * as cartActions from "../../store/actions/cart";
import * as productsActions from "../../store/actions/products";
import Colors from "../../constants/Colors";
import * as AddMinusButton from "../../components/UI/AddMinusButton";
const ProductsOverviewScreen = (props) => {
const [isLoading, setIsLoading] = useState(false);
const [isRefreshing, setIsRefreshing] = useState(false);
const [error, setError] = useState();
const products = useSelector((state) => state.products.availableProducts);
const dispatch = useDispatch();
const loadProducts = useCallback(async () => {
setError(null);
setIsRefreshing(true);
try {
await dispatch(productsActions.fetchProducts());
} catch (err) {
setError(err.message);
}
setIsRefreshing(false);
}, [dispatch, setIsLoading, setError]);
useEffect(() => {
const willFocusSub = props.navigation.addListener(
"willFocus",
loadProducts
);
return () => {
willFocusSub.remove();
};
}, [loadProducts]);
useEffect(() => {
setIsLoading(true);
loadProducts().then(() => {
setIsLoading(false);
});
}, [dispatch, loadProducts]);
const selectItemHandler = (id, title) => {
props.navigation.navigate("ProductDetail", {
productId: id,
productTitle: title,
});
};
if (error) {
return (
<View style={styles.centered}>
<Text>An error occurred!</Text>
<Button
title="Try again"
onPress={loadProducts}
color={Colors.primary}
/>
</View>
);
}
if (isLoading) {
return (
<View style={styles.centered}>
<ActivityIndicator size="large" color={Colors.primary} />
</View>
);
}
if (!isLoading && products.length === 0) {
return (
<View style={styles.centered}>
<Text>No products found. Maybe start adding some!</Text>
</View>
);
}
return (
<FlatList
onRefresh={loadProducts}
refreshing={isRefreshing}
data={products}
keyExtractor={(item) => item.id}
renderItem={(itemData) => (
<ProductItem
image={itemData.item.imageUrl}
title={itemData.item.title}
price={itemData.item.price}
onSelect={() => {
selectItemHandler(itemData.item.id, itemData.item.title);
}}
>
<AddMinusButton />
<Button
color={Colors.primary}
title="To Cart"
onPress={() => {
dispatch(cartActions.addToCart(itemData.item));
}}
/>
</ProductItem>
)}
/>
);
};
ProductsOverviewScreen.navigationOptions = (navData) => {
return {
headerTitle: "All Products",
headerLeft: (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title="Menu"
iconName={Platform.OS === "android" ? "md-menu" : "ios-menu"}
onPress={() => {
navData.navigation.toggleDrawer();
}}
/>
</HeaderButtons>
),
headerRight: (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title="Cart"
iconName={Platform.OS === "android" ? "md-cart" : "ios-cart"}
onPress={() => {
navData.navigation.navigate("Cart");
}}
/>
</HeaderButtons>
),
};
};
const styles = StyleSheet.create({
centered: { flex: 1, justifyContent: "center", alignItems: "center" },
});
export default ProductsOverviewScreen;