Rendering DB entry in Expo - javascript

This is my first go at a expo/react native app, and i have struck trouble,
I am able to console.log my firestore db entries fine, but i cant seem to work out how to render them to a view, and to make location cards like the attached image, 1
Can anyone help?
import React, { Component } from "react";
import { View, Text, StyleSheet } from "react-native";
import firebase from "firebase";
require("firebase/firestore");
const config = {
};
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
var db = firebase.firestore();
class componentName extends Component {
componentDidMount() {
db.collection("event")
.get()
.then((snapshot) => {
snapshot.docs.forEach((doc) => {
console.log(doc.data());
});
});
}
render() {
return (
<View style={styles.container}>
<Text>d</Text>
</View>
);
}
}
export default componentName;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
});

For this you need to create a state and need to include your db entries in state, some thing like this:
constructor(props){
super(props);
this.state={
data:[]
}
}
And set your db entries like this in state data:
componentDidMount() {
db.collection("event")
.get()
.then((snapshot) => {
this.setState({
data : snapshot.docs
})
}
And in view you can render it like this:
return (
<View style={styles.container}>
{
this.state.data.map((item,key) =>{
return(
<Text>{item.campusName}</Text>
<Text>{item.campusAddress}</Text>
<Text>{item.campusTimings}</Text>
)
})
}
</View>
);
Hope this helps!

Related

Unable to find the react native variable "ConnectionStatus"

I am trying to implement a code that tests the internet connectivity using react native NetInfo from '#react-native-community/netinfo'. It is giving me an error that says "Can't find variable: connectionStatus". I tried my best declare properly but for some reason it is giving the error above.
import React, { Component } from 'react'
import NetInfo from '#react-native-community/netinfo';
import { ActivityIndicator, StyleSheet,View, Text } from 'react-native'
import { WebView } from 'react-native-webview';
export default class BrowserScreen extends Component {
constructor(props) {
super(props);
this.state = {
connectionStatus: false,
}
}
componentDidMount() {
const {navigation} = this.props;
this.focusListener = navigation.addListener('didFocus', () => {
this.checkConnected();
})
}
async checkConnected() {
const networkState = await NetInfo.fetch();
if (networkState.isConnected) {
this.setState({ connectionStatus: true });
}
}
LoadingIndicatorView() {
return <ActivityIndicator
color='#009b88'
size='large'
style={styles.ActivityIndicatorStyle}
/>
}
render() {
let url = this.props.navigation.getParam('webUrl');
console.log(url) ;
return (
/**
* use the webview here to display the webpage
*/
connectionStatus ? (
<WebView
source={{ uri: url }}
renderLoading={this.LoadingIndicatorView}
startInLoadingState={true}
/>
) :
(
<View>
<Text> No Connection !!!!</Text>
</View>)
)
}
}
const styles = StyleSheet.create({
ActivityIndicatorStyle: {
flex: 1,
justifyContent: 'center'
}
})
connectionStatus is stored in state, refer to it as this.state.connectionStatus

ScrollView in React Native

I created a simple app, that shows a few pictures with titles. It is something like a film gallery, where you can observe all enable films. But when I try to add ScrollView element it doesn't work when I try to scroll on my emulated Android device. How can I fix it? My code looks like this:
import React, { Component } from 'react'
import { View, ScrollView, StyleSheet } from 'react-native'
import { Header, ImageCard } from './src/components/uikit'
const url = 'https://s3.eu-central-1.wasabisys.com/ghashtag/RNForKids/00-Init/data.json'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
title: 'STAR GATE',
data: []
};
}
componentDidMount = async () => {
try {
const response = await fetch(url)
const data = await response.json()
this.setState({ data })
}
catch (e) {
console.log(e)
throw e
}
}
render() {
const { title, data } = this.state
const { container } = style
return (
<View>
<Header title={title} />
<ScrollView>
<View style={container}>
{
data.map(item => {
return <ImageCard data={item} key={item.id} />
})
}
</View>
</ScrollView>
</View>
)
}
}
const style = StyleSheet.create({
container: {
marginTop: 30,
flexDirection: 'row',
flexWrap: 'wrap',
flexShrink: 2,
justifyContent: 'space-around',
marginBottom: 150
}
})
I made it with a guide, so it should work. (Youtubes author hasn't this problem on his video).
The View inside ScrollView looks problematic. Try something like:
<ScrollView contentContainerStyle={container} >
{
data.map(item => {
return <ImageCard data={item} key={item.id} />
})
}
</ScrollView>

FlatList - Fetching Data From Postman Localhost url

Hi Everyone,
I'm very beginner to this platform.
Could any one help me to where i did mistake in the following code?
i'm Using SQL server for database
In App.js I have tried the below code...
import React, { Component } from 'react';
import {
StyleSheet,
View,
ActivityIndicator,
TouchableOpacity,
Text,
Dimensions,
FlatList
} from 'react-native';
export default class App extends React.Component {
//Set States
constructor(props)
{
super(props);
this.state={
isLoading: true,
dataSource: []
}
}
//Get Data From API
componentDidMount()
{
fetch('http://localhost:7483/api/StudentData/')
.then((response)=>response.json())
.then((responseJson)=>{
this.state({
isLoading: false,
dataSource: responseJson
})
})
}
_renderItem=({item,index}) => {
return(
<View>
<Text>Hello</Text>
</View>
);
}
render()
{
let {container}=styles
let {dataSource,isLoading}=this.state
//Use FlatList for Display Data
return(
<View style={container}>
<FlatList
data={dataSource}
renderItem={this._renderItem}
keyExtractor={(item,index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
flex:1,
justifyContent:'center',
alignItems:'center'
},
welcome:{
fontSize:20,
textAlign:'center',
margin:10
}
});
I'm getting data in postman url from SQL server
I'm getting this warning msg
Empty Emulator Screen
Console Warning msg
In the android emulator URL with localhost not working, so you must set ipv4 address instead of that.
Also change this.state -> this.setState
Add you IP address instead of localhost
1.) Run cmd
2.) type ipconfig
3.) Scroll Down to IPv4 Address. . . . . . . . . . . : 192.168.**.**
4.) Copy this IP and replace it in place of localhost
5.) Done
Get your IP like this
So Suppose if your IPv4 address is - 192.168.100.84 then
Your fetch should look like this
fetch('http://192.168.100.84:7483/api/StudentData/')
Also for setting state after fetch
You have to do like this
this.setState({ isLoading: false, dataSource: responseJson })
Instead of this
this.state({ isLoading: false, dataSource: responseJson })
In your render part write like this
return(
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={this._renderItem}
keyExtractor={(item,index) => index.toString()}
/>
</View>
);
Your App.js using Function Component
import React, { Component, useState, useEffect } from 'react';
import {
StyleSheet,
View,
ActivityIndicator,
TouchableOpacity,
Text,
Dimensions,
FlatList,
} from 'react-native';
export default function App() {
const [State, setState] = useState({
loading: true,
dataSource: [],
});
useEffect(() => {
GetData();
}, []);
const GetData = async () => {
const result = await fetch('http://192.168.43.159:7483/api/StudentData/');
const response = await result.json();
setState({
...State,
isLoading: false,
dataSource: response,
});
};
const _renderItem = ({ item, index }) => {
return (
<View>
<Text>Hello</Text>
</View>
);
};
return (
<View style={styles.container}>
<FlatList
data={State.dataSource}
renderItem={_renderItem}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
},
});

ReactNative : Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state

This is my code, I can't seem to find the problem. I've researched the problem but wasn't able to find a solution so I'm turning to the StackOverflow gods for some help !
As you can see I want to load the fonts in my LoadingScreen and move to the next screen once it's done. if there's an easier way to proceed let me know.
import React from 'react';
import { StyleSheet, View, AsyncStorage, Alert, ActivityIndicator } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient'
import * as Font from 'expo-font';
import * as firebase from "firebase";
export default class Loading extends React.Component {
constructor(props) {
super(props);
this.state = {
fontLoaded: false,
client: {
uid: ""
}
};
}
async componentWillMount() {
//Load fonts + Login to Firebase + capture user ID
let self = this;
await Font.loadAsync({
"Roboto-Regular": require("../assets/fonts/Roboto-Regular.ttf"),
"Courgette-Regular": require("../assets/fonts/Courgette-Regular.ttf"),
"Raleway-Regular": require("../assets/fonts/Raleway-Regular.ttf")
})
await firebase.auth().signInAnonymously().catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
Alert.alert("Error code : " + errorCode, errorMessage)
});
//Register the UID
await this.setState({ uid: firebase.auth().currentUser.uid })
this.setState({
client: {
...this.state.client,
uid: firebase.auth().currentUser.uid
}
});
await this.setState({ fontLoaded: true })
}
render() {
if (this.state.fontLoaded) {
return (
this.props.navigation.navigate("Home", { client: this.state.client })
)
}
return (
<View style={styles.container}>
<LinearGradient
colors={["#5B86E5", "#36D1DC"]}
style={{ flex: 1 }}
>
<View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>
<ActivityIndicator size="large" color="#FFF" />
</View>
</LinearGradient>
</View >
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
});
I think it is better to do load your Home Screen. It is not efficient to do an action like fetching data in a page and navigate to another page after action completion. I think it is better to fetch your data in componentDidMount lifecycle and when data received change your fontLoaded to true as below:
import React from 'react';
import { StyleSheet, View, AsyncStorage, Alert, ActivityIndicator } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient'
import * as Font from 'expo-font';
import * as firebase from "firebase";
export default class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
fontLoaded: false,
client: {
uid: ""
}
};
}
async componentDidMount() {
//Load fonts + Login to Firebase + capture user ID
let self = this;
await Font.loadAsync({
"Roboto-Regular": require("../assets/fonts/Roboto-Regular.ttf"),
"Courgette-Regular": require("../assets/fonts/Courgette-Regular.ttf"),
"Raleway-Regular": require("../assets/fonts/Raleway-Regular.ttf")
})
await firebase.auth().signInAnonymously().catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
Alert.alert("Error code : " + errorCode, errorMessage)
});
//Register the UID
await this.setState({ uid: firebase.auth().currentUser.uid })
this.setState({
client: {
...this.state.client,
uid: firebase.auth().currentUser.uid
}
});
await this.setState({ fontLoaded: true })
}
render() {
if (this.state.fontLoaded) {
return (
........... Any code that presents in your Home component
)
}
return (
<View style={styles.container}>
<LinearGradient
colors={["#5B86E5", "#36D1DC"]}
style={{ flex: 1 }}
>
<View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>
<ActivityIndicator size="large" color="#FFF" />
</View>
</LinearGradient>
</View >
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
});
I hope it was helpful for you. If it was your desired solution please vote me up:)
You are mixing UI (render method) and functions (navigate inside the render). That method will execute multiple times, when React detects an update in the state or props.
If this is just a loading screen then remove the conditional from the render and just show a loading screen and navigate to the next screen from the componentDidMount method, which will only trigger once when the screen loads up.
That should remove the error. Basically, remove the setState({fontLoaded: true}) and just navigate to the next screen from there.

React Native Flatlist returns the wrong number of empty rows

When I run the code below, it displays 3 empty rows. It should be showing two rows each with a color and enddate and I want to use the 'Parent' as the unique key. The 'Parent' is the unique key created by Firebase when color and enddate were pushed to Firebase with '.push'.
I've tried all sorts of things to get it to display. I did get content to display when I made the 'renderItems' return 'this.state.list', but that returned 3 lines all with the same data, which is the content of the last array on the console log.
I would really appreciate some help to get this working.
Here is the code, a copy of Firebase database and the console.log. Please note that the Firebase 'goal' has been changed to 'color'.
import React, { Component } from 'react';
import { Text, FlatList, View, Image } from 'react-native';
import firebase from 'firebase';
import { Button, Card, CardSection } from '../common';
import styles from '../Styles';
class List extends Component {
static navigationOptions = {
title: 'List',
}
constructor(props) {
super(props);
this.state = {
list: [],
};
}
componentDidMount() {
const { currentUser } = firebase.auth();
const Parent = firebase.database().ref(`/users/${currentUser.uid}/Profile`);
Parent.on(('child_added'), snapshot => {
this.setState({ list: [snapshot.key, snapshot.val().color, snapshot.val().enddate] });
console.log(this.state.list);
});
}
keyExtractor = (item, index) => index;
render() {
return (
<Card>
<View style={{ flex: 1 }}>
<FlatList
data={this.state.list}
keyExtractor={this.keyExtractor}
extraData={this.state}
renderItem={({ item }) => (
<Text style={styles.listStyle}>
{ item.color }
{ item.enddate }
</Text>
)}
/>
</View>
<CardSection>
<Button
style={{
flex: 1,
flexDirection: 'row'
}}
onPress={() => this.props.navigation.navigate('NextPage', { name: 'user' })}
title="Go to next page"
>
Go to next page
</Button>
</CardSection>
</Card>
);
}
}
export { List };
This is the correct way to store the list
componentDidMount() {
const { currentUser } = firebase.auth();
const Parent = firebase.database().ref(`/users/${currentUser.uid}/Profile`);
Parent.on(('child_added'), snapshot => {
const newChild = {
key: snapshot.key,
color: snapshot.val().color,
enddate: snapshot.val().enddate
}
this.setState((prevState) => ({ list: [...prevState.list, newChild] }));
console.log(this.state.list);
});
}
and your keyExtractor
keyExtractor = (item, index) => item.key;

Categories

Resources