Sorry in advance if this is a silly question but I'm going in circles here. I'm pretty new to react and node, and looking to connect my react native front end with my node back end. Pretty much every tutorial I read is telling me to "paste the fetch api code after the class declaration and before the render method", but I don't have a class declaration or render method in any of my code, so I'm a little confused about where to put the fetch api code? I don't know if this makes a huge difference but each screen of my app is in it's own file as it's own function and I am using a stack navigator to get between the screens with it's functionality contained in another file for the stack navigator.
If anyone could offer me some help I would really appreciate it, I am beyond confused about what to do.
Included below is my Login Screen function so you can see what I mean when I say the screens are set up as functions. All other screens are laid out the same way. Please let me know if you need to see anything else and I will edit and add it in!
import React from 'react';
function LoginScreen() {
return(
<View style={{ alignItems: "center", marginTop: 24 }}>
<Text style={styles.text}>
Login Screen
</Text>
</View>
);
}
export default LoginScreen
Again, I would appreciate any help anyone could give me as this is driving me demented and I would really like to get this working!
With functional components, you declare your "methods" inside your function:
function LoginScreen() {
const submit = () => {
//do something
}
return <View>
<Button title="Submit" onPress={submit} />
</View>
}
So, You are trying to use Functional Components instead of Class Based Component.
In Functional Components to send FetchAPI Request we use React Hooks, useEffect to send api request, and save the return data of API Request in another hook useState.
Please read more about React Hooks here,
https://reactjs.org/docs/hooks-intro.html
In your above scenario fetch api request with functional components will be something like this,
import React, {useEffect, useState} from 'react';
function LoginScreen() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('yourapi.com/user')
.then(res => res.json())
.then(data => setData(data));
}, []);
return(
<View style={{ alignItems: "center", marginTop: 24 }}>
<Text style={styles.text}>
// You Can Use Your Data Here {data}
Login Screen
</Text>
</View>
);
}
export default LoginScreen
A most pro and less verbose way to do it is using axios library. Check this code out:
import React, { useState, useEffect } from 'react';
import { View, Text } from 'react-native';
import axios from 'axios';
export default function LoginScreen() {
const [user, setUser] = useState({});
const termToSearchFor = 'edilsonlm217';
useEffect(() => {
async function loadAPI() {
const response = await axios.get(`https://api.github.com/users/${termToSearchFor}`);
setUser(response.data);
}
loadAPI();
}, []);
return (
<View style={{ alignItems: "center", marginTop: 24 }}>
<Text>
{user.bio}
</Text>
</View>
);
}
This piece of code searchs for my user "edilsonlm217" in the public github's API right away after the component load. It gets the response from response.data and set it to user state then print my bio on screen.
Don't forget to install axios as dependecy to your project before use it.
Related
I've been using the library to create bottom sheet modals for my react native app, but it's doesn't seem to work on Android, but on iOS it does. I used the same backdrop component and handle component suggested in the docs, and everything is contained is the provider, and SafeAreaView
my package.json includes
"#gorhom/bottom-sheet": "^3.6.5",
"react-native-reanimated": "^2.0.0",
and the code is structured like this:
<BottomSheetModal ref={reference_settings}
index = {1}
enableOverDrag={true}
onChange = {(index) => { if(index === 0) { reference_settings.current.dismiss(); } }}
snapPoints = {[-1, '50%', '70%']}
backdropComponent={Backdrop}
handleComponent ={(props) => (<Belt {...props} />)}
style ={styles.sheet}
>
<BottomSheetView style={[styles.content]}>
<View style={{ width, height: '100%', overflow: 'hidden', backgroundColor: scheme === 'dark' ? '#000' : '#FFF', paddingHorizontal: 10 }}>
// the functions inside
</View>
</BottomSheetView>
</BottomSheetModal>
I used the right configuration for babel for react-native-reanimated including the plugin, but it shows up and then I can't drag to close.
I know it's a bit late to answer for you but I would like to add for others. Assuming you already installed react-native-gesture-handler you should also add some lines of code to your MainActivity.java.
Don't forget to wrap your Root App Component like this in the index.js file
place the the import statement at the top of index.js
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
import {AppRegistry} from 'react-native';
AppRegistry.registerComponent(appName, () => gestureHandlerRootHOC(App));
more details
I am using Expo for my app. I have a horizontal Flatlist where I render my data react native paper's Card. I saw Card have onPress function. I used that to navigate the another page. But onPress function does not trigger on Android device. I know React native's touchable-opacity have positioning issue on Android. I tried hitSlop and inline styling zIndex but still does not work. I also wrap my card with react-native's touchable-opacity and play with positioning still did not help me, only it works when i used react-native-gesture-handler's touchable-opacity but then it does not work on IOS. Hope anyone can help me...
import React from 'react';
import { Card } from 'react-native-paper';
import { useNavigation } from '#react-navigation/native';
interface Iprops {
item: string;
}
export default function RenderCard({ item }: Iprops) {
const navigation = useNavigation();
return (
<Card
hitSlop={{ "bottom": 30, "top": 30, "right": 30, "left": 30 }}
onPress={() => {
navigation.navigate(`detail`, { // THIS DOES NOT TRIGGER ON ANDROID
"id": `${item.pk}`
});
}}
style={{ "marginBottom": 20 }}>
<Card.Cover
source={{ "uri": `${item.img_url}` }} />
<Card.Actions>
<Card.Title title={item.name} subtitle="Card Subtitle" />
</Card.Actions>
</Card>
);
}
I've noticed that using onPressIn or onPressOut does work on Android within an absolute positioned flatlist, but onPress does not work. I hope this might be of help to someone out there looking for an answer.
You'll need to use the TouchableOpacity element from react-native-gesture-handler.
Like you told, you should add touchable opacity to the element you are rendering on the card. TouchableOpacity can be tricky. So, first give it a styling of borderWidth:1 and borderColor to see the actual touchable area on the screen. Then you start to bring them together with the icon or the image or whatever you are rendering. TouchableOpacity works but the positioning can be tricky. You have to understand it to use it better. Think touchableOpacity as a view with borders then it'll be easier to grasp. Also, if you dont give touchableOpacity an absolute position in the styling it will be out of the screen somewhere, I was never be able to bring it to somewhere that I can see to position it. So you can add 'position' as well.
I gave up on positioning and render my component's based on Platform.
Platform.OS === `ios` ?
<Card
onPress={() => {
navigation.navigate(`detail`, {
"id": `${item.pk}`
});
}}
style={{ "marginBottom": 20 }}>
<Card.Cover source={{ "uri": `${item.img_url}` }} />
<Card.Actions>
<Card.Title title={item.name} subtitle="Card Subtitle" right={Beer} />
</Card.Actions>
</Card> :
<TouchableOpacity
onPress={() => {
navigation.navigate(`detail`, {
"id": `${item.pk}`
});
}}
>
<Card style={{ "marginBottom": 20 }}>
<Card.Cover source={{ "uri": `${item.img_url}` }} />
<Card.Actions>
<Card.Title title={item.name} subtitle="Card Subtitle" right={Beer} />
</Card.Actions>
</Card>
</TouchableOpacity>;
As the question says my Webview component wont load its content. I have no errors poping up or any problem in the conosle related to WebView. I am using expo.
On the other hand when using Iframe I have no problem loading the content running test on web browser but wont work when running test on mobile device. I have tried every solution proposed by others in here but nothing seems to work. I even tried using the iframe inside the WebView using html instead of uri, also nesting the WebView component into a View and giving it flex:1 but still nothing comes up on the screen but a small red dot up in the right corner.
As you can see all the test I've done with the commented code. The first (commented) function is using the Iframe component and the second (not commented) is only WebView.
My code looks like this:
import React from 'react';
import { StyleSheet, Text, Button, View, Dimensions } from 'react-native';
import Iframe from 'react-iframe';
import Header from './Header';
import ButtonMenu from './ButtonMenu';
import { WebView } from 'react-native-webview';
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width;
// export default function NatureQuestGps({navigation}) {
// return (
// <View style={styles.pageNatureQuest}>
// <View style={styles.headerContainer}>
// <Header/>
// <ButtonMenu color='#49AC72' onPress={()=> navigation.toggleDrawer()} />
// </View>
// <Iframe url="https://www.google.com/maps/d/embed?mid=11fEhEZiv72kKKy7XbbQ3GIufEcTpWUa2"
// width="400px"
// height="400px"
// display="initial"
// position="relative"/>
// </View>
// );
// }
export default function NatureQuestGps() {
return (
<View style={{ flex: 1, alignItems: 'flex-end' }}>
<WebView
source= {{ uri: 'https://www.google.com/maps/d/embed?mid=11fEhEZiv72kKKy7XbbQ3GIufEcTpWUa2'}}
style={styles.webview}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={false}
scalesPageToFit={true}
/>
</View>
);
}
const styles = StyleSheet.create({
pageNatureQuest:{
flex:1,
flexDirection:'column',
alignItems:'center',
},
headerContainer: {
width:'100%',
backgroundColor:'#ededed',
},
webview: {
flex: 1,
backgroundColor: 'yellow',
width: deviceWidth,
height: deviceHeight
}
});
Thanks in advance for anyone taking the time to help
I found the solution and it turns out that WebView component works when testing in mobile with EXPO but naver loaded in my browser, and the Iframe that worked in my browser but was not working in my mobile. Anyways the answer is that if you want a google maps trail or parcour to work for mobile and also web you will need a library to create your own maps routes and trails. But if you are only making a mobile app go for the WebView component although it possibly wont work in your computer browser for tests.
My react-native app look totally fine on most Android devices (and iOS) I tested on emulator, but some devices with noticeable curved screen on top (Google Pixel 4, API 29), it shows a big empty region on top of the phone.
This does not look normal. Do you know how to fix it ?
I am using SafeAreaView but without any Android specific padding/margin.
<SafeAreaView style={{flex:1}}>
... My App Code come here.
</SafeAreaView>
I also tried to remove the the SafeAreaView and used regular View instead but it still wont go away.
Just for testing I removed everything and added a hello world test screen.
It still gives same wide empty space.
My App.js:
export default class Main extends React.Component {
constructor(props) {
super (props);
}
render () {
return (
<View style={{flex:1, backgroundColor: 'white'}}>
<Text> Hello World, How to fix this ? </Text>
</View>
);
}
}
AppRegistry.registerComponent(appName, () => Main);
You can't remove it, it's a display bug on the Pixel 4 emulator. A physical Pixel 4 doesn't have that gap.
See my other answer for a detailed explanation.
You can achieve this simply by hiding your StatusBar just like this:
import React from "react";
import { StatusBar, View, Text } from "react-native";
export default class Main extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
StatusBar.setHidden(true);
}
render() {
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<Text> Hello World, How to fix this ? </Text>
</View>
);
}
}
Update: set StatusBar's transluent attribute to true along with make its' background as transparent like this:
import React, { Component } from "react";
import { StatusBar, View, Text } from "react-native";
export default class Main extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
StatusBar.setTranslucent(true);
StatusBar.setBackgroundColor("transparent");
}
render() {
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<Text> Hello World, How to fix this ? </Text>
</View>
);
}
}
Have you tried using this way
<StatusBar translucent={true} hidden={true} /> {/* <--- Here */}
Check statusbar component where you can draw an app under the status bar by using the property named translucent. Reference link
I managed to fix this by going to AVD Manager -> Click on Wipe Data
Img
I would like to place a component, in this case a simple text app version number that is clickable and will force a version refresh, on the screen of a react native app. I would like this to be visible no matter what platform the app is running on (iOS/Android/device/simulator/react-native-web), and no matter what else happens on the screen in the app. If there are other things displayed, I'd like this component to display on top of them. I have not been able to do this.
(Aside: This is for debugging, as I have not found that the Expo system reliably reloads and presents the current version of the app. If someone would like to comment with a solution to this, great).
I've tried many things, for example, including the component below in the main app.js file. In this case, it will display for all screens on iOS simulator, but not on Android device. From other posts, I understand that this may have to do with Android limitations.
Thank you for your help.
import React, { Component } from 'react'
import { StyleSheet, Text, View,TouchableHighlight } from 'react-native'
import { Ionicons } from '#expo/vector-icons'
import { Updates } from 'expo';
export default class AppVersion1 extends Component {
_onPressButton = ()=> {
AppConsole.log('Pressed reload')
Updates.reload()
}
render(){
return(<View style={styles.appVersionPosition}>
<TouchableHighlight onPress={this._onPressButton}>
<Text
style={styles.appversion}
onPress={this.reload}
>
<Ionicons name="md-refresh" /> Beta043</Text>
</TouchableHighlight>
</View>)}
}
const styles = StyleSheet.create({
appversion: {
color:'white',
backgroundColor:'#68a0cf',
textAlign: 'center',
fontSize:10,
zIndex: 99999
},
appVersionPosition: {
position: 'absolute',
top: '7%',
left: 0,
backgroundColor: 'grey',
zIndex: 99999
}
})