pass database data to another screen in react native - reactjs

Now I wanted to implement a function that when I click on a list of data from mysql server on my react native app, it will move to another screen and pass the detail of the data into it here is the code that I have implement
const GetJobDetail=useCallback= (user,job, jobid, machinecode, startTime) =>{
navigation.navigate('Jobview', {
UserId : user,
Job : job,
JobId:jobid,
MachineCode : machinecode,
StartTime : startTime
},[]);
}
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Button title={item.job} style={styles.rowViewContainer} onPress={()=>navigation.navigate(GetJobDetail(item.user,item.job,item.jobid,item.machinecode,item.startTime))}/>
)}
/>
)}
</View>
);
I have already successful fetch the data into my react native apps, the data look like
the data is only show the job of the user instead of showing all detail if I enter userid='1111' then it will only show the job for userid='1111'. but now i wish to implement that if I clicked the job in this list it will move to next screen and send all the details to that screen using route.params. I have tried using callback function but it gave me error "useCallback" is read-only.
I also founded some source from other site but it is in class component the code will look like this.
i am sure that this first is the function that pass the value to another screen
GetStudentIDFunction=(student_id,student_name, student_class, student_phone_number, student_email)=>{
this.props.navigation.navigate('Third', {
ID : student_id,
NAME : student_name,
CLASS : student_class,
PHONE_NUMBER : student_phone_number,
EMAIL : student_email
});
}
and this one is calling the function and pass the data to another screen
renderRow={ (rowData) => <Text style={styles.rowViewContainer}
onPress={this.GetStudentIDFunction.bind(
this, rowData.student_id,
rowData.student_name,
rowData.student_class,
rowData.student_phone_number,
rowData.student_email
)} >
{rowData.student_name}
</Text> }
pls help me to point out what is my mistake or error. Thanks
update:
after tried multiple time finally it works with this code. On the first page it get the data
const GetDetail=(id,user,job,jobid,machinecode,startTime)=>{
navigation.navigate('JobView',{Id:id,UserId:user,Job:job,JobId:jobid,MachineCode:machinecode,StartTime:startTime});
}
return (
<View style={{ flex: 1, padding: 24,backgroundColor:'cyan' }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text style={styles.rowViewContainer} onPress={()=>{GetDetail(item.id,item.user,item.job,item.jobid,item.machinecode,item.startTime)}}>{item.job}</Text>
)}
/>
)}
</View>
);
}
On this screen it pass the data from previous screen by using route.params&&route.params.variable\\variable=your own variable that carry the data from th eprevious screen
useEffect(()=>{
setCode(route.params && route.params.MachineCode)
setUserid(route.params && route.params.UserId)
setJob(route.params && route.params.Job)
setJid(route.params && route.params.JobId)
setStarttime(route.params && route.params.StartTime)
setId(route.params && route.params.Id)
},[]
)
Hope this will help you guys when faced the same problem :)

Store your data in some useState after fetching. You can send data to another screen/component in two ways:
You can pass data as props or use a callBack if those screens/components are in parent-child relationship.
Parent to child: Pass as props
<FlatList
data={customerData}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
keyExtractor={(item, index) => index}
renderItem={({item, index}) => (
<KYC_ListCell
itemdata={customerData[index]}
onItemClick={() => {
props.updateCustomerInformation(customerData[index]);
navigation.navigate('Customer360Info');
}}
/>
Using a call back to pass data from child to parent
//Parent
<HeaderView
username={'HelpDesk'}
showHeaderWithSearch
placeholderText={'Customer ID'}
showRefreshIcon
onMenuClick={() => {
setModalVisible(true);
}}
onRefreshClicked={() => {
getComplaintsListOnPageLoad();
}}
onSearchClicked={text => {
setSearch(text);
getSearchedItem(text);
}}
/>
//child
<Search
value={search}
placeholderText={props.placeholderText}
onChangeText={text => setSearch(text)}
onClearText={() => setSearch('')}
onSearchPressed={() => props.onSearchClicked(search)}
/>
You can pass data while navigating as route param

Related

How to Limit render element Flat List and add more content in React Native

I want like that flatlist render only 5 checkbox items and then when I click to +5 more button it will show 5 more checkbox list.In this all checkbox list appearing but i want only five
Please help me how to achieve that
Thanks in advance
const renderResourceList = renderData => {
return (
<FlatList
data={renderData}
initialNumToRender={5}
maxToRenderPerBatch={5}
pagingEnabled={true}
nestedScrollEnabled={true}
renderItem={({item}) => (
<View style={styles.card}>
<TouchableOpacity
onPress={() => {
if(resourceTypeArray.includes(item)){
setResourceTypeArray(currentList => {
return currentList.filter(items => items !== item);
});
}
else{
setResourceTypeArray(currentList => [
...currentList,
item
]);
}
onSetResourceType(item);
}}
style={styles.modalBtn}>
<Icon
name={
resourceTypeArray.includes(item) ? 'checkbox-marked' : 'checkbox-blank-outline'
}
size={18}
color="#353C3C"
style={{bottom: -1}}
/>
<View style={styles.textWrapper}>
<Text style={styles.modalText}>{item.charAt(0)}
{item.toLowerCase().slice(1).replace(/_/g, ' ')}</Text>
</View>
</TouchableOpacity>
</View>
)}
/>
);
};
I tried but this not working
I used a package called flatlist-react to handle this for me. A decent tutorial for this can be found here.
With this package, you can directly specify and limit the items rendered with the limit prop. Here is an example:
<FlatList
limit="2,-2"
list={people}
renderItem={Person}
/>
If you keep track of the limit prop variables using state, you can dynamically change these values when you click 5+ more in order to render whatever part of your data you would like.

React Native -- FlatList data updated but Render Item does not when data changed

I am using a FlatList in which I am using a single component on two pages. One is home and next is Favourites. My issue is this I have created a poll card in which when a user submit an answer to the poll then both list must be updated based on list data changed. I have saved the list in context and changing the values in array from context but my card values not updated.
FlatList Code (Feed.js)
const { feedArray,setFeedArray} = useContext(AuthContext);
<FlatList
extraData={feedArray}
data={feedArray}
renderItem={({item, index}) => (
<RenderCard
item={item}
navigation={navigation}
index={index}
managePost={false}
isPaymentReport={false}
isBookmark={false}
previewMode={false}
isPinnedPost={false}
isPaymentExplorer={false}
/>
)}
numColumns={1}
keyExtractor={(item, index) => index}
contentContainerStyle={{
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'transparent',
}}
showsVerticalScrollIndicator={false}
keyboardShouldPersistTaps="handled"
onEndReachedThreshold={0.05}
onScrollBeginDrag={() => setLoadingMore(true)}
onEndReached={handleOnEndReached}
ListFooterComponent={() => loadingMore && <ListFooterComponent />}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={() => onRefresh()}
tintColor={Colors.light.black}
/>
}
/>
Poll Card Code (Poll.js)
On Button Pressed to submit Poll
<TouchableOpacity onPress={updateSurveyCard}>Submit</TouchableOpacity>
Update Survey Card with submitted option
const updateSurveyCard = value => {
let newArray = feedArray;
const index = newArray.findIndex(object => {
return object.cardId === item.cardId;
});
if (index !== -1) {
newArray[index].surveyArray = [{"percentage": 100, "response": "F"}, {"percentage": "0", "response": "T"}];
}
setFeedArray([... newArray]);
}
but the issue is that when I change this data and set in setFeedArray again the my feedArray called again and I am able to get all the list on Feed.js but my Poll.js has not updated with latest data. I want to updated "surveyArray" with lates values on Poll.js
Please help
Try to store data in useState();
const [feedArray,setFeedArray] = useState(AuthContext);

Will memoization prevent my React component from rerendering?

I'm struggling to understand what causes my component to rerender as there is no state present here. Code to focus on is Flatlist as this is React Native but this is about React and not specifically RN. As you can see inside Flatlist I render renderPost. I know that renderPost, aka reusable component PostListItem rerenders because this console.log you can see inside flatlist gives me repeated keys, and even console logging postsSortedByDate shows me that they render few times. Because of this, I even have a warning child list keys must be unique while I definitely gave flatlist unique IDs from my array, that warning is because of these rerendering. I guess I need to use Memo somewhere?:
const FeedScreen: React.FC<FeedScreenProps> = ({ navigation }) => {
const { postsSortedByDate } = checkPostsContext();
const navigateToCreatePostScreen = async () => {
navigation.navigate("CreatePostScreen");
};
const renderPost: ListRenderItem<IPost> = ({ item }) => (
<PostListItem post={item} key={item.uniquePostID} />
);
return (
<ScreenContainer>
<SafeAreaView>
<Header
containerStyle={styles.containerStyleHeader}
headerTitle="Factory X Feed"
rightIcon="add-photo-alternate"
onPressRightIcon={navigateToCreatePostScreen}
/>
</SafeAreaView>
{postsSortedByDate.length === 0 ? (
<View style={styles.noPostsContainer}>
<Text>
No posts exist at the moment, please create one by tapping on the
image icon in the header. In the meantime, as indicated by the
spinner below, we will continue to try to fetch posts in case some
do exist but are just loading slowly.
</Text>
<ActivityIndicator size="large" color="#0000ff" />
</View>
) : (
<FlatList
data={postsSortedByDate}
renderItem={renderPost}
keyExtractor={(item, index) => {
console.log("IDS:", item.uniquePostID.toString());
//HERE IS THE ISSUE as here I see same keys rendering //multiple times, and I checked and I did not save posts in a wrong way //for few of them to have the same key somehow. Its now about that. //Even logging posts themselves(here) shows me they re render.
return item.uniquePostID.toString();
}}
/>
)}
</ScreenContainer>
);
};
My PostListItem component:
const PostListItem: React.FC<PostItemProps> = ({ post }) => {
return (
<View style={styles.container}>
{post.postImage ? (
<Lightbox
renderContent={() => {
return (
<Image
source={{ uri: post.postImage }}
resizeMode="cover"
style={[
styles.imageInLightbox,
{
width: width,
height: height,
},
]}
/>
);
}}
>
<Image
source={{ uri: post.postImage }}
resizeMode="contain"
style={styles.image}
/>
</Lightbox>
) : null}
<React.Fragment>
{post.postDescription ? (
<Text style={styles.textStyle}>
{hashtagFormatter(post.postDescription)}
</Text>
) : (
<Text style={styles.textStyle}>{defaultPostDescription}</Text>
)}
</React.Fragment>
</View>
);
So why is PostListItem, I mean renderPost rerendering and how to fix it?

How to cancel all subscriptions and asynchronous tasks in a useEffect cleanup function

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
The page here includes a selectable FlatList. However if I select another element too fast (before the whole flatList is loaded), the error above will appear. I'm not sure which function I should put in useEffect and what return statements I should put so that it cleans up (or let the previous flatList stop loading).
The error specifically pointed out the Item function, as shown in the code below (unrelated codes skipped)
function ChampSelect({navigation, route}) {
...
const Item = ({ item, onPress, weight, color}) => (
<TouchableOpacity onPress={onPress}>
<Image
source={require('../pictures/champions/' + item + '.png')}
style= {[styles.image, color]}
/>
<Text style={[styles.title, weight]}>
{item}
</Text>
</TouchableOpacity>
)
const renderItem = ({ item }) => {
const fontWeight = item === selectedChamp ? 'bold' :'normal';
const borderColor = item === selectedChamp ? '#6BDB5A' :'black'
return (
<Item
item={item}
onPress={() => setSelectedChamp(item)}
weight={{ fontWeight }}
color = {{borderColor}}
/>
)
}
...
return (
...
<View style={{marginLeft: 48, marginTop: 40}}>
<FlatList
ListHeaderComponent={renderHeader}
numColumns={3}
horizontal={false}
data={data}
extraData={selectedChamp}
renderItem={renderItem}
keyExtractor={item => item}
/>
</View>
</View>
)
}
Any help would be appreciated!

React Native - passing data model from Flat list

I have a FlatList:
<ScrollView nestedScrollEnabled={true}>
<Screen style={styles.screen}>
<TouchableOpacity onPress={() => navigation.navigate("ProfileDetailScreen")}>
<FlatList
data={users}
renderItem={renderItem}
keyExtractor={item => item.uid}
/>
</TouchableOpacity>
</Screen>
</ScrollView>
And Im getting some data from firebase like:
useEffect(() => {
firebaseUsers
.onSnapshot(
querySnapshot => {
const newUsers = []
querySnapshot.forEach(doc => {
const user = doc.data()
user.id = doc.id
newUsers.push(user)
});
setUsers(newUsers)
},
error => {
console.log(error)
}
)
}, [])
The data I get from firebase has name, image and age (and more more fields).
How can I pass all the data for a single user into the ProfileDetailedScreen?
Not sure the correct way to achieve this (not sure If I need to create data models etc?)
I don't know firebase that well but I have experience in RN. From what I'm understanding, you're going to want to make the renderItem function in your FlatList a function that returns a TouchableOpacity with navigation to the ProfileDetailedScreen component while also passing the user object. You'll display the user details in the ProfileDetailedScreen.
Passing items in navigation documentation
/* 'item' is a user from the users array you passed into the data property of your FlatList above */
renderItem = ({item}) => (
<TouchableOpacity onPress={() => navigation.navigate("ProfileDetailScreen", item)}>
<Text> item?.name </Text> {/* show brief info about user */}
</TouchableOpacity>
)
If you're using Redux for your application state, you could also navigate only to "ProfileDetailScreen" and dispatch an action that sets a currentUser in state. Your "ProfileDetailsScreen" would then pull the currentUser from state. This way has more moving parts but the component piece would look something like this:
/* 'item' is a user from the users array you passed into the data property in your FlatList above */
renderItem = ({item}) => (
<TouchableOpacity onPress={this.setUserAndNavigate.bind(this, item)}>
<Text> item?.name </Text> {/* show brief info about user */}
</TouchableOpacity>
)
setUserAndNavigate = (user) => {
this.props.setUser(user);
navigation.navigate("ProfileDetailScreen");
}

Resources