getting lat/long coordinates from firebase/firestore collection - firebase

im relative new to react native and firebase and it would be awesome if anyone could help me with this problem. currently when im adding new posts to my firebase collection i display all post with a flatlist and it works fine. but is it possible to get only the currentLatitude and currentLongitude for my markers? my target is to generate a new marker for each post.
Events = []
this.firestore.collection("Events").get().then(snapshot => {
snapshot.forEach(doc => {
Events.push(doc.data())
})
})
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
mapType='hybrid'
showsUserLocation style={{flex: 1}}>
<MapView.Marker
coordinate={{latitude: //currentLatitude,
longitude: //currntLongitude}}
title={("Test")}
description={("Test")}
/>
</MapView>
</View>
</SafeAreaView>
);
}
}

#DevAS thanks for your patience.. this was made from 3 different .js files.. but I don't now how to get it just into the map.js.
The final result should look something like this:
enter image description here
Everything except for the lat/lng cords are supposed to be in the callout-window.
Item.js:
import { Ionicons } from '#expo/vector-icons';
import React from 'react';
import { Image, StyleSheet, Text, View } from 'react-native';
import Fire from '../screens/Fire'
const profileImageSize = 36;
const padding = 12;
export default class Item extends React.Component {
state = {
user: {}
};
componentDidMount() {
const user = this.props.uid || Fire.shared.uid;
this.unsubscribe = Fire.shared.firestore
.collection("users")
.doc(user)
.onSnapshot(doc => {
this.setState({ user: doc.data() });
});
if (!this.props.imageWidth) {
// Get the size of the web image
Image.getSize(this.props.image, (width, height) => {
this.setState({ width, height });
});
}
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { title, address, name, imageWidth, imageHeight, image, currentLatitude, currentLongitude } = this.props;
// Reduce the name to something
const imgW = imageWidth || this.state.width;
const imgH = imageHeight || this.state.height;
const aspect = imgW / imgH || 1;
return (
<View>
<Header image={{ uri: this.state.user.avatar }} name={this.state.user.name} />
<Image
resizeMode="contain"
style={{
backgroundColor: "#D8D8D8",
width: "100%",
aspectRatio: aspect
}}
source={{ uri: image }}
/>
<Metadata
name={this.state.user.name}
address={address}
title={title}
currentLongitude={currentLongitude}
currentLatitude={currentLatitude}
/>
</View>
);
}
}
const Metadata = ({ name, address, title, currentLongitude, currentLatitude}) => (
<View style={styles.padding}>
<IconBar />
<Text style={styles.text}>{name}</Text>
<Text style={styles.subtitle}>{address}</Text>
<Text style={styles.subtitle}>{title}</Text>
<Text style={styles.subtitle}>Lat: {currentLatitude}</Text>
<Text style={styles.subtitle}>Lng: {currentLongitude}</Text>
</View>
);
const Header = ({ name, image }) => (
<View style={[styles.row, styles.padding]}>
<View style={styles.row}>
<Image style={styles.avatar} source={image} />
<Text style={styles.text}>{name}</Text>
</View>
<Icon name="ios-more" />
</View>
);
const Icon = ({ name }) => (
<Ionicons style={{ marginRight: 8 }} name={name} size={26} color="black" />
);
const IconBar = () => (
<View style={styles.row}>
<View style={styles.row}>
<Icon name="ios-heart-empty" />
<Icon name="ios-chatbubbles" />
<Icon name="ios-send"/>
</View>
<Icon name="ios-bookmark" />
</View>
);
const styles = StyleSheet.create({
text: { fontWeight: "600" },
subtitle: {
opacity: 0.8
},
row: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
},
padding: {
padding
},
avatar: {
aspectRatio: 1,
backgroundColor: "#D8D8D8",
borderWidth: StyleSheet.hairlineWidth,
borderColor: "#979797",
borderRadius: profileImageSize / 2,
width: profileImageSize,
height: profileImageSize,
resizeMode: "cover",
marginRight: padding
}
});
List.js
import React from 'react';
import { FlatList } from 'react-native';
import Footer from './Footer';
import Item from './Item';
class List extends React.Component {
renderItem = ({ item }) => <Item {...item} />;
keyExtractor = item => item.key;
render() {
const { onPressFooter, ...props } = this.props;
return (
<FlatList
keyExtractor={this.keyExtractor}
ListFooterComponent={footerProps => (
<Footer {...footerProps} onPress={onPressFooter} />
)}
renderItem={this.renderItem}
{...props}
/>
);
}
}
export default List;
FeedScreen.js
import firebase from "firebase";
import React, { Component } from "react";
import { LayoutAnimation, RefreshControl } from "react-native";
import List from "../components/List";
import Fire from "./Fire";
// Set the default number of images to load for each pagination.
const PAGE_SIZE = 5;
console.disableYellowBox = true;
export default class FeedScreen extends Component {
state = {
loading: false,
data: {}
};
componentDidMount() {
// Check if we are signed in...
if (Fire.shared.uid) {
// If we are, then we can get the first 5 posts
this.makeRemoteRequest();
} else {
// If we aren't then we should just start observing changes. This will be called when the user signs in
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.makeRemoteRequest();
}
});
}
}
// Append the item to our states `data` prop
addPosts = posts => {
this.setState(previousState => {
let data = {
...previousState.data,
...posts
};
return {
data,
// Sort the data by timestamp
posts: Object.values(data).sort((a, b) => a.timestamp < b.timestamp)
};
});
};
// Call our database and ask for a subset of the user posts
makeRemoteRequest = async lastKey => {
// If we are currently getting posts, then bail out..
if (this.state.loading) {
return;
}
this.setState({ loading: true });
// The data prop will be an array of posts, the cursor will be used for pagination.
const { data, cursor } = await Fire.shared.getPaged({
size: PAGE_SIZE,
start: lastKey
});
this.lastKnownKey = cursor;
// Iteratively add posts
let posts = {};
for (let child of data) {
posts[child.key] = child;
}
this.addPosts(posts);
// Finish loading, this will stop the refreshing animation.
this.setState({ loading: false });
};
// Because we want to get the most recent items, don't pass the cursor back.
// This will make the data base pull the most recent items.
_onRefresh = () => this.makeRemoteRequest();
// If we press the "Load More..." footer then get the next page of posts
onPressFooter = () => this.makeRemoteRequest(this.lastKnownKey);
render() {
// Let's make everything purrty by calling this method which animates layout changes.
LayoutAnimation.easeInEaseOut();
return (
<List
refreshControl={
<RefreshControl
refreshing={this.state.loading}
onRefresh={this._onRefresh}
/>
}
onPressFooter={this.onPressFooter}
data={this.state.posts}
/>
);
}
}

Related

Testing React Native with Jest - Doesn't test 'onPress' and 'onChangeText'

I'm testing a component called ForgotPasswordComponent in React Native with Jest. The code for the component is seen here:
import { StyleSheet, View, ToastAndroid, Dimensions } from 'react-native'
import React, {useState} from 'react'
import {Button, Headline, Text, TextInput} from 'react-native-paper';
import { getAuth, sendPasswordResetEmail } from "firebase/auth";
import { useNavigation } from '#react-navigation/native';
import { ScaledSheet } from 'react-native-size-matters';
const {height, width} = Dimensions.get('window')
export default function ForgotPasswordComponent() {
const [email, setEmail] = useState('');
const auth = getAuth();
const navigation = useNavigation();
const forgotPassword = () => {
sendPasswordResetEmail(auth, email)
.then(() => {
ToastAndroid.show('Reset password mail sent successfully!', ToastAndroid.LONG);
})
.catch(() => {
ToastAndroid.show('Error: Please check your entered e-mail!', ToastAndroid.LONG)
});
}
return (
<View style={styles.container}>
<View>
<Button style={styles.buttonBack} uppercase={false} onPress={() => {navigation.navigate("Login")}}>
<Text style={styles.buttonTextGoBack}>Go back</Text>
</Button>
</View>
<View>
<Headline style={styles.headline}>Forgot your password? No problem!</Headline>
</View>
<View>
<Text style={styles.inputText}>Email:</Text>
<TextInput style={styles.input} placeholder="Enter your email" value={email} onChangeText={text => setEmail(text)}></TextInput>
</View>
<View>
<Button style={styles.buttonResetPassword} mode="contained" uppercase={false} onPress={forgotPassword}>
<Text style={styles.buttonTextResetPassword}>Reset password</Text>
</Button>
</View>
</View>
)
}
const styles = ScaledSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
marginBottom: '200#s'
},
headline: {
fontSize: '18#s',
marginTop: '60#s',
padding: '20#s',
},
inputText: {
paddingLeft: '14#s',
paddingTop: '6#s',
fontSize: '14#s'
},
input: {
padding: '10#s',
margin: '15#s',
width: width * 0.8,
height: height * 0.03,
fontSize: '14#s'
},
buttonResetPassword: {
width: width * 0.5,
},
buttonBack: {
paddingRight: '260#s',
width: width * 1.1,
},
buttonTextResetPassword: {
color: 'white',
fontSize: '14#s'
},
buttonTextGoBack: {
fontSize: '14#s'
}
})
As it is seen, it uses two functions from Firebase and the component have very little functionality.
Here is the testcases that I have wrote so far:
import React from 'react';
import renderer from 'react-test-renderer'
import ForgotPasswordComponent from '../components/ForgotPassword/ForgotPasswordComponent';
import { NavigationContainer } from '#react-navigation/native';
import { fireEvent, render } from '#testing-library/react-native';
import { Button, TextInput } from 'react-native-paper';
jest.useFakeTimers()
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
const mockGetAuth = jest.fn()
const mockSendPassword = jest.fn(() => {
return Promise.resolve(true)
})
jest.mock('firebase/auth', () => {
return {
getAuth: () => mockGetAuth,
sendPasswordResetEmail: () => mockSendPassword
}
})
//Testing that navigation is working
describe("Navigation working", () => {
it("calls useNavigation and navigates", () => {
const mockedNavigate = jest.fn();
jest.mock('#react-navigation/native', () => (
{ useNavigation: () => ({ navigate: mockedNavigate }) }));
const onPress = jest.fn(mockedNavigate);
const {getByText} = render(
<Button onPress={onPress}>Go Back</Button>,
);
fireEvent.press(getByText('Go Back'));
expect(mockedNavigate).toBeCalledTimes(1);
})
})
//Testing buttons and inputfield are working
describe('Buttons and input on press working', () => {
it('Go back onpress is called', () => {
const onPress = jest.fn();
const {getByText} = render(
<Button onPress={onPress}>Go Back</Button>,
);
fireEvent.press(getByText('Go Back'));
expect(onPress).toBeCalledTimes(1);
});
it('Reset onpress is called', () => {
const onPress = jest.fn();
const {getByText} = render(
<Button onPress={onPress}>Reset password</Button>,
)
fireEvent.press(getByText('Reset password'));
expect(onPress).toBeCalledTimes(1);
})
it('Email onChange is called', () => {
const onChangeTextMock = jest.fn();
const {getByPlaceholderText} = render(
<TextInput placeholder="Enter your email" onChangeText={onChangeTextMock}/>
);
fireEvent.changeText(getByPlaceholderText("Enter your email"), "test#gmail.com");
expect(onChangeTextMock).toBeCalled();
})
});
//Snapshot testing
test('renders forgotPasswordComponent correctly 1', () => {
const tree = renderer.create(
<NavigationContainer>
<ForgotPasswordComponent/>
</NavigationContainer>)
.toJSON();
expect(tree).toMatchSnapshot();
});
All the testcases runs succesfully, but when I inspect the code coverage I don't understand why my onPress function on line 30 and onChangeText function on line 39 are red. It is like they are not getting tested at all despite I have made testcases for them.
Besides are there any solution of how I can test the Firebase function sendPasswordResetEmail is called when the button is pressed and it shows the succesfully toast-message?

How do I search for titles in Cloud Firestore using the SearchBar from react-native-elements?

I imported a SearchBar from react-native-elements and I want to be able to search my articles by title. So the field I should be able to pull and search from Cloud Firestore is called 'title'. I'm not sure how to do that.
import React, { Component } from "react";
import { StyleSheet, View, FlatList } from "react-native";
import { AppleCard } from "react-native-apple-card-views";
import firebase from "../../Firebase";
import { SearchBar } from 'react-native-elements';
import { ScrollView } from "react-native-gesture-handler";
export default class Discover extends Component {
constructor(props) {
super();
this.ref = firebase.firestore().collection("articles").where("publish", "==", true);
this.unsubscribe = null;
this.state = {
articles: [],
search: '',
};
}
onCollectionUpdate = (querySnapshot) => {
const articles = [];
querySnapshot.forEach((doc) => {
const { title, subtitle, imageUrlPath } = doc.data();
articles.push({
key: doc.id,
doc, // DocumentSnapshot
title,
subtitle,
imageUrlPath,
});
});
this.setState({
articles,
});
};
componentDidMount() {
this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate);
}
updateSearch = (search) => {
this.setState({ search });
};
renderItem = ({ item }) => {
return (
<View>
<View style={styles.card}>
<AppleCard
largeTitle={item.title}
smallTitle=""
footnoteText={item.subtitle}
resizeMode="cover"
source={{uri:item.imageUrlPath}}
onPress={() => {
this.props.navigation.navigate("Content", {
articlekey: `${JSON.stringify(item.key)}`,
});
}}
/>
</View>
</View>
);
};
render() {
const { search } = this.state;
return (
<ScrollView>
<SearchBar
placeholder="Search here..."
onChangeText={this.updateSearch}
value={search}
platform='ios'
/>
<View style={styles.discover}>
<FlatList data={this.state.articles} renderItem={this.renderItem} />
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
discover: {
flex: 1,
backgroundColor: "#FBFCFC",
alignItems: "center",
justifyContent: "center",
},
card: {
padding: 15,
},
});

How to Use Multiple Array to store state values With Redux in React Native

Here I have use Redux to manage state value but is not working..
And i have two arrays to hold the state values but it is not showing any record i don't know why it is not working..
notesReducer.js
import remove from 'lodash.remove'
// Action Types
export const ADD_NOTE = 'ADD_NOTE'
export const DELETE_NOTE = 'DELETE_NOTE'
export const ADD_NUMBER = 'ADD_NUMBER'
export const DELETE_NUMBER = 'DELETE_NUMBER'
// Action Creators
let noteID = 0
let numberID = 0
export function addnote(note) {
return {
type: ADD_NOTE,
id: noteID++,
note
}
}
export function deletenote(id) {
return {
type: DELETE_NOTE,
payload: id
}
}
export function addnumber(number) {
return {
type: ADD_NUMBER,
id: numberID++,
number
}
}
export function deletenumber(id) {
return {
type: DELETE_NUMBER,
payload: id
}
}
// reducer
const INITIAL_STATE = {
note: [], // for holds notes
number: [] // for holds numbers
};
function notesReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case ADD_NOTE:
return {
...state,
note: [
...state.note,
{
id: action.id,
note: action.note
}
]
};
case DELETE_NOTE:
const note = remove(state.note, obj => obj.id != action.payload);
return {...state, note};
case ADD_NUMBER:
return {
...state,
number: [
...state.number,
{
id: action.id,
number: action.number
}
]
};
case DELETE_NUMBER:
const number = remove(state.number, obj => obj.id != action.payload);
return {...state, number}
default:
return state
}
}
export default notesReducer
And single Store
store.js
import { createStore } from 'redux'
import notesReducer from './notesApp'
const store = createStore(notesReducer)
export default store
ViewNotes.js
import React from 'react'
import { Button, StyleSheet, View, FlatList } from 'react-native'
import { Text, FAB, List } from 'react-native-paper'
import { useSelector, useDispatch } from 'react-redux'
import { addnote, deletenote } from '../redux/notesApp'
import { Ionicons } from "react-native-vector-icons";
import Header from '../components/Header'
function ViewNotes({ navigation }) {
const notes = useSelector(state => state)
const dispatch = useDispatch()
const addNote = note => dispatch(addnote(note))
const deleteNote = id => dispatch(deletenote(id))
return (
<>
<Header titleText='White List' />
<View style={styles.container}>
<Button title="Go back" onPress={() => navigation.goBack()} />
{notes.length === 0 ? (
<View style={styles.titleContainer}>
<Text style={styles.title}>You do not have any notes</Text>
</View>
) : (
<FlatList
data={notes}
renderItem={({ item }) => (
<List.Item
title={item.note.noteTitle}
description={item.note.noteValue}
right={props => <List.Icon {...props} icon="close" />}
descriptionNumberOfLines={1}
titleStyle={styles.listTitle}
onPress={() => deleteNote(item.id)}
/>
)}
keyExtractor={item => item.id.toString()}
/>
)}
<FAB
style={styles.fab}
small
icon='plus'
label='Add new number'
onPress={() =>
navigation.navigate('AddNotes', {
addNote
})
}
/>
</View>
</>
)
}
ViewNotes.navigationOptions = {
title : 'Always Allows Calls'
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingHorizontal: 10,
paddingVertical: 20
},
titleContainer: {
alignItems: 'center',
justifyContent: 'center',
flex: 1
},
title: {
fontSize: 20
},
fab: {
position: 'absolute',
margin: 20,
right: 0,
bottom: 10
},
listTitle: {
fontSize: 20
}
})
export default ViewNotes
AddNote.js
import React, { useState } from 'react'
import { View, StyleSheet } from 'react-native'
import { IconButton, TextInput, FAB } from 'react-native-paper'
import Header from '../components/Header'
function AddNote({ navigation }) {
const [noteTitle, setNoteTitle] = useState('')
const [noteValue, setNoteValue] = useState('')
function onSaveNote() {
navigation.state.params.addNote({ noteTitle, noteValue })
navigation.goBack()
}
return (
<>
<Header titleText='Add a new number' />
<IconButton
icon='close'
size={25}
color='white'
onPress={() => navigation.goBack()}
style={styles.iconButton}
/>
<View style={styles.container}>
<TextInput
label='Add Title Here'
value={noteTitle}
mode='outlined'
onChangeText={setNoteTitle}
style={styles.title}
/>
<TextInput
label='Add Note Here'
value={noteValue}
onChangeText={setNoteValue}
mode='flat'
multiline={true}
style={styles.text}
scrollEnabled={true}
returnKeyType='done'
blurOnSubmit={true}
/>
<FAB
style={styles.fab}
small
icon='check'
disabled={noteTitle == '' ? true : false}
onPress={() => onSaveNote()}
/>
</View>
</>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingHorizontal: 20,
paddingVertical: 20
},
iconButton: {
backgroundColor: 'rgba(46, 113, 102, 0.8)',
position: 'absolute',
right: 0,
top: 40,
margin: 10
},
title: {
fontSize: 24,
marginBottom: 20
},
text: {
height: 300,
fontSize: 16
},
fab: {
position: 'absolute',
margin: 20,
right: 0,
bottom: 0
}
})
export default AddNote
It is not Showing any record So How i fixed it..
Please Help me..
Change useSelector(state => state) to :
useSelector(state => state.note)
Because your store is like {note: [], number: []}

How can I get my Firebase Data into React-Native Map Marker instead of a Flatlist

Im trying to get all my Firebase Docs/Posts into React-Native-Maps Markers and show them on a map(like AirBnB for example) but couldn't found out the wright way till now..
all my functions are working fine with a flatlist as you can see in the screenshot but how can I get the data into the markers? Ive tried to get the data + renderItem function from the Flatlist tag and put it into the MapView tag but it didn't work because of the open brace/funtion.
Im fairly new in JS/RN.. so im maybe not really able to understand all of the technical terminology. I would be very thankful if someone has a solution for that.. im struggling for several weeks with this issue.
Fire.js function:
export async function getMarker(markerRetreived) {
var marker = [];
var snapshot = await firebase.firestore()
.collection('Events')
.orderBy('createdAt')
.get()
snapshot.forEach((doc) => {
const markerItem = doc.data();
markerItem.id = doc.id;
marker.push(markerItem);
});
markerRetreived(marker);
}
Working Flatlist (map.js):
class FocusOnMarkers extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
marker: []
}
}
onMarkerReceived = (marker) => {
this.setState(prevState => ({
marker: prevState.marker = marker
}));
}
componentDidMount() {
getMarker(this.onMarkerReceived);
}
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList style={styles.container}
data={this.state.marker}
renderItem={({ item }) => {
return (
<ListItem
containerStyle={styles.listItem}
title={`lat: ${item.geopoint.latitude}`}
subtitle={`lng: ${item.geopoint.longitude}`}
titleStyle={styles.titleStyle}
subtitleStyle={styles.subtitleStyle}
leftAvatar={{
size: 'large',
rounded: false,
source: item.image && { uri: item.image }
}}
/>
)
}
}
/>
</SafeAreaView>
)
}
}
React-Native-Map:
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
mapType='hybrid'
showsUserLocation style={{flex: 1}}>
<MapView.Marker
data={this.state.marker}
coordinate={{latitude: this.state.geopoint.latitude,
longitude:this.state.geopoint.longitude}}
title={("Test")}
description={("Test")}
/>
</MapView>
</View>
</SafeAreaView>
);
}
}
I just wanna let you now that I solved the problem by myself.
just changed a line of code in my map.js =>
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
mapType='hybrid'
showsUserLocation style={{flex: 1}}>
{this.state.marker.map(item => (
<MapView.Marker
coordinate={{latitude: item.geopoint.latitude,
longitude: item.geopoint.longitude}}
title={("Test")}
description={("Test")}
/>
)}
</MapView>
</View>
</SafeAreaView>
);
}
}

How to view react native application database with tables

I'm creating a react native app. now I want to view my App database tables.
I don't know how many tables are in my SQLite database.
I am new in react native development & SQLite please help. to solve this issue
You can solve this problem through the Table View command. It can also be used to view data for that table.
/*Screen to view all the table*/
import React from 'react';
import { FlatList, Text, View } from 'react-native';
import { openDatabase } from 'react-native-sqlite-storage';
var db = openDatabase({ name: 'UserDatabase.db' });
export default class ViewAllTable extends React.Component {
constructor(props) {
super(props);
this.state = {
FlatListItems: [],
};
db.transaction(tx => {
tx.executeSql('SHOW TABLES', [], (tx, results) => {
var temp = [];
for (let i = 0; i < results.rows.length; ++i) {
temp.push(results.rows.item(i));
}
this.setState({
FlatListItems: temp,
});
});
});
}
ListViewItemSeparator = () => {
return (
<View style={{ height: 0.2, width: '100%', backgroundColor: '#808080' }} />
);
};
render() {
return (
<View>
<FlatList
data={this.state.FlatListItems}
ItemSeparatorComponent={this.ListViewItemSeparator}
keyExtractor={(item, index) => index.toString()}
renderItem={({item, index }) => (
<View key={item[index]} style={{ backgroundColor: 'white', padding: 20 }}>
<Text>Table: {item[index]}</Text>
</View>
)}
/>
</View>
);
}
}

Resources