React Native Relase, Debug apk crashes in physical devices - android

I followed the facebook documentation on how to generate signed apk exactly. But still I am getting error: undefined is not an object (evaluating 'e.length'
Here is the screenshot
However, the app works fine in Android Emulator with command react-native run-android.
But, I got the issue which was causing the app to crash. It was native-base.
Here is the following code in my App.js:
import React, { Component } from 'react';
import {Text} from 'react-native';
import { Container, Header, Content, Form,Text, Item, Input, Label, Button }
from 'native-base';
export default class ReactNativeExample extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
this.doSignIn = this.doSignIn.bind(this);
}
doSignIn() {
let formdata = new FormData();
formdata.append("username", this.state.username)
formdata.append("password", this.state.password)
fetch('http://someweb.com/loginUser',{
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formdata
}).then((response) => response.json())
.then((responseData) => {
console.log("Inside responsejson");
if(responseData.error != true) {
console.log('You have logged in...');
}
}).done();
}
render() {
return (
<Container>
<Header />
<Content>
<Form>
<Item floatingLabel style={{margin: 8}}>
<Label>Username</Label>
<Input ref="username" onChangeText={(username) =>
this.setState({username})}/>
</Item>
<Item floatingLabel last style={{margin: 8}}>
<Label>Password</Label>
<Input ref="username" onChangeText={(password) =>
this.setState({password})}/>
</Item>
<Button block info style={{margin: 8}} onPress={this.doSignIn}>
<Text>Login</Text>
</Button>
</Form>
</Content>
</Container>
<Text> Hello </Text>
);
}
}
I want to know what is wrong with the above native-base code that is making the App crash? Is there any way I can make native-base code work?
Thank You.
ReactNative version: 0.50.1

That's because there is import duplicates of Text component
import { Text } from 'react-native';
import { Container, Header, Content, Form,Text, Item, Input, Label, Button }
from 'native-base';
You can import both Text components via as like this
import { Text as NativeText } from 'react-native';
And then use NativeText. Otherwise, do not duplicate your imports.

tried your code. Was able to generate an apk successfully. Didn't find any issue while running the apk. Posting the code.
import React, { Component } from "react";
import { Container, Header, Content, Form, Text, Item, Input, Label,Button } from "native-base";
export default class ReactNativeExample extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
};
this.doSignIn = this.doSignIn.bind(this);
}
doSignIn() {
let formdata = new FormData();
formdata.append("username", this.state.username);
formdata.append("password", this.state.password);
fetch("https://httpbin.org/", {
method: "post",
headers: {
"Content-Type": "multipart/form-data",
},
body: formdata,
})
.then(response => console.log("response", response))
.done();
}
render() {
return (
<Container>
<Header />
<Content>
<Form>
<Item floatingLabel style={{ margin: 8 }}>
<Label>Username</Label>
<Input ref="username" onChangeText={username => this.setState({ username })} />
</Item>
<Item floatingLabel last style={{ margin: 8 }}>
<Label>Password</Label>
<Input ref="username" onChangeText={password => this.setState({ password })} />
</Item>
<Button block info style={{ margin: 8 }} onPress={this.doSignIn}>
<Text>Login</Text>
</Button>
</Form>
</Content>
</Container>
);}
}
When using NativeBase components use <Text/> from 'native-base'

Related

React native mapbox-gl crashes with react-navigation

I have a problem. When I display a map with #rnmapbox/maps and that I want to navigate in my screens, the app freeze then crashes. I'm pretty sure that this is a rnmapbox problem because when I remove the code between <MapboxGL.MapView> and <MapboxGL.MapView/>, navigation works fine.
I use #react-navigation/native and #react-navigation/native-stack
Note that this issus don't append on iOS, only on Android.
Record of the issue : https://vimeo.com/723749736
Here is my code :
App.js
import React from 'react';
import MapScreen from './src/screens/MapScreen';
import PlaceDetailsScreen from './src/screens/PlaceDetailsScreen';
import VideoPlayerScreen from './src/screens/VideoPlayerScreen';
import {createNativeStackNavigator} from '#react-navigation/native-stack';
import {NavigationContainer} from '#react-navigation/native';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {GestureHandlerRootView} from 'react-native-gesture-handler';
function App() {
const Stack = createNativeStackNavigator();
return (
<SafeAreaProvider>
<GestureHandlerRootView style={{flex: 1}}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Map"
component={MapScreen}
options={{headerShown: false}}
/>
<Stack.Group>
<Stack.Screen name="Details" component={PlaceDetailsScreen} />
<Stack.Screen
name="VideoPlayer"
component={VideoPlayerScreen}
options={{headerShown: false}}
/>
</Stack.Group>
</Stack.Navigator>
</NavigationContainer>
</GestureHandlerRootView>
</SafeAreaProvider>
);
}
export default App;
MapScreen.js
import React, {useState, useRef, useMemo, useCallback, useEffect} from 'react';
import {View, Text, PermissionsAndroid, Platform} from 'react-native';
import MapboxGL from '#rnmapbox/maps';
import BottomSheet, {BottomSheetScrollView} from '#gorhom/bottom-sheet';
import Styles from '../../Styles';
import PlaceBtn from '../components/PlaceBtn/PlaceBtn';
import IconPin from './../assets/icons/icon-locationPin.svg';
MapboxGL.setAccessToken(
'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
);
function MapScreen({navigation}) {
const [hasGeolocPermission, setHasGeolocPermission] = useState(false);
const [currentRegion, setCurrentRegion] = useState([4.824, 45.76]); //longitude, latitude
const [userLocation, setUserLocation] = useState();
const [nearestPoints, setNearestPoints] = useState([]);
const markers = require('../data/markers.json');
const route = require('../data/route.json');
const routeLine = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: route.points,
},
},
],
};
const bottomSheetRef = useRef(null);
const snapPoints = useMemo(() => ['13%', '75%', '100%'], []);
const handleSheetChanges = useCallback(index => {
console.log('handleSheetChanges', index);
}, []);
const requestLocationPermission = async () => {
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('location uses is granted');
setHasGeolocPermission(true);
} else {
console.log(granted);
console.log('location access denied');
}
} catch (error) {
console.warn('error while request location : ', error);
}
}
};
useEffect(() => {
requestLocationPermission();
}, []);
return (
<View style={Styles.container}>
<MapboxGL.MapView style={Styles.map} scaleBarEnabled={false}>
<MapboxGL.UserLocation
animated
showsUserHeadingIndicator
minDisplacement={1}
onUpdate={position => {
console.log('position : ', position);
}}
/>
<MapboxGL.Camera centerCoordinate={currentRegion} zoomLevel={14} />
{markers.map((marker, index) => {
if (marker.category === 'introduction') {
console.log('intro');
} else {
return (
<MapboxGL.PointAnnotation
key={index}
id={marker.id + ''}
coordinate={[marker.longitude, marker.latitude]}>
<IconPin width={35} height={35} fill={'#00c0aa'} />
</MapboxGL.PointAnnotation>
);
}
})}
<MapboxGL.ShapeSource id="line1" shape={routeLine}>
<MapboxGL.LineLayer
id="linelayer1"
style={{lineColor: 'red', lineWidth: 5}}
/>
</MapboxGL.ShapeSource>
</MapboxGL.MapView>
<BottomSheet
ref={bottomSheetRef}
handleIndicatorStyle={Styles.handleIndicator}
index={0}
snapPoints={snapPoints}
onChange={handleSheetChanges}>
<View style={Styles.bottomSheetContent}>
<Text style={Styles.bottomSheetTitle}>{route.name}</Text>
<BottomSheetScrollView>
{markers.map((place, index) => {
return (
<PlaceBtn
place={place}
navigation={navigation}
//isNear={nearestPoints.includes(place.id)}
/>
);
})}
</BottomSheetScrollView>
</View>
</BottomSheet>
</View>
);
}
export default MapScreen;
PlaceDetailsScreen.js
import React from 'react';
import {View, Text, TouchableOpacity} from 'react-native';
function PlaceDetailsScreen({navigation}) {
return (
<>
<TouchableOpacity
style={{backgroundColor: '#00FF00'}}
onPress={() => navigation.navigate('Map')}>
<Text>Go to MAP</Text>
</TouchableOpacity>
<TouchableOpacity
style={{backgroundColor: '#00FF00'}}
onPress={() => navigation.navigate('VideoPlayer')}>
<Text>Go to Video Player</Text>
</TouchableOpacity>
</>
);
}
```
I had the same problem. In my case I have a modal that is persistent through all screens and that modal shrinks when user swipes down like in youtube. After I initialized map inside modal, whenever I try to change screen my app were first freezing then crashing.
My solution was to render map only when modal is expanded. So I made a conditional rendering. Checked whether modal is shrinked or not. If shrinked, then render the map, else don't render. Thus my navigation worked without any problem.
This was my case and that's how I solved it:
// I use reduxjs toolkit.
// Since this modal is gonna be persistent through all screens
// It's best to store translateY value in redux.
const Modal = useAppSelector((state) => state.Modal);
const translateY = useSharedValue(Modal.translateY);
// I watch this variable with an useEffect hook to dynamically update redux value
const [translateYState, setTranslateYState] = useState(translateY.value);
useEffect(() => {
dispatch(setTranslateY(translateYState));
}, [translateYState]);
// translateYState's value is dynamically updating by a pan gesture detector
// translateYState value to be 0 means modal is expanded and user is using the modal
return (
<>
{translateYState==0 && (
<MapboxGL.MapView style={styles.map}></MapboxGL.MapView>
)}
</>
)
You can un-render the map when the modal which has title "Les Sens de Lyon" expands. If you are worried about your map data, you can store the map data for example all locations of markers in redux to be persistent but if your app is a single page app it should not be a problem else you can use redux.

ESLint: App.js (22:21) Parsing error: Unexpected token, expected ";"

The error:
ESLint: App.js (22:21) Parsing error: Unexpected token, expected ";"
20 | export default function App() {
21 |
> 22 | constructor(props){
| ^
23 | super(props)
24 |
25 | this.state = ({ (null)
Code:
import React from 'react';
import { StyleSheet, Image, Text, View } from 'react-native';
import { Container, Content, Header, Form, Input, Item, Button, Label, } from 'native-base';
import * as firebase from 'firebase';
var firebaseConfig = {
apiKey: "AIzaSyB387ecmvoIcHvboydLrxL_vwBJqWHhXGw",
authDomain: "shootgeorgiaapp.firebaseapp.com",
databaseURL: "https://shootgeorgiaapp.firebaseio.com",
projectId: "shootgeorgiaapp",
storageBucket: "shootgeorgiaapp.appspot.com"
};
if (!firebase.apps.length){
firebase.initializeApp(firebaseConfig);
}
export default function App() {
constructor(props){
super(props)
this.state = ({
email:'',
password:''
})
}
signUpUser = (email,password) =>{
try{
if(this.state.password.length<6){
alert("გთხოვთ მიუთთოთ 6-ზე მეტ ციფრიანი პაროლი")
return;
}
firebase.auth().createUserWithEmailAndPassword(email,password)
}
catch(error){
console.log(error.toString())
}
}
logInUser = (email,password) =>{
}
return (
<Container style={styles.container}>
<Form>
<Image
style={{height:170 , width:170, alignItems: 'center',}}
source={require('./img/logo.png')}
/>
<Item floatingLabel>
<Label>Email</Label>
<Input
autoCorrect={false}
autoCapitalize="none"
onChangeText={(email) => this.setState({email})}
/>
</Item>
<Item floatingLabel>
<Label>Password</Label>
<Input
secureTextEntry={true}
autoCorrect={false}
autoCapitalize="none"
onChangeText={(password) => this.setState({password})}
/>
</Item>
<Button style={{marginTop:10} }
full
rounded
success
onPress={() => this.logInUser(this.state.email,this.state.password)}
>
<Text style={{color:'white'}}>Log in</Text>
</Button>
<Button style={{marginTop:10} }
full
rounded
primary
onPress={() => this.signUpUser(this.state.email,this.state.password)}
>
<Text style={{color:'white'}}>Sign in</Text>
</Button>
</Form>
</Container>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
padding: 10,
},
});
I tried thousands of things but nothing works.
your declaring a function 'App' and treating it as a class. A simple solution is you use classes instead
export default class App extends Component{
//
}
in order to inherit what you're looking for.
Security flag: don't post your api keys anywhere in the internet or sensitive information

Native-Base Picker does not work properly Android - Does not trigger function onValueChange

I'm using Picker component of Native-Base for my react-native application. On IOS everything is ok, whereas, on Android side I can not trigger function I added on onValueChange.
Is there anyone faced this issue before?
How did you fix it? I stuck here almost a day.
Here is my code.
<Picker style={{ width: 200, height: 40}}
iosHeader="Branch"
Header="Branch"
mode="dropdown"
textStyle={{color: 'white'}}
placeholder="Branch"
headerBackButtonText="Geri"
selectedValue={this.state.selectedBranch}
onValueChange={(value)=>this.onBranchSelected(value)}
>
{this.state.branches.map((branches, i)=>{
return(
<Picker.Item label={branches.address_line} value={branches.id} key={i}/>
);
}
)}
</Picker>
It does not call the function onBranchSelected on Android.
I tried your code and was working fine for me.
Pasting my code
import React, { Component } from "react";
import { Platform } from "react-native";
import { Container, Header, Title, Content, Button, Icon, Text, Right, Body, Left, Picker, Form } from "native-base";
export default class PickerExample extends Component {
constructor(props) {
super(props);
this.state = {
branches: [
{ address_line: 'address 1', id: 1 },
{ address_line: 'address 2', id: 2 },
{ address_line: 'address 3', id: 3 },
{ address_line: 'address 4', id: 4 },
{ address_line: 'address 5', id: 5 }],
selected1: 1
};
}
onBranchSelected(value) {
this.setState({
selectedBranch: value
});
}
render() {
return (
<Container>
<Header>
<Left>
<Button transparent>
<Icon name="arrow-back" />
</Button>
</Left>
<Body>
<Title>Picker</Title>
</Body>
<Right />
</Header>
<Content>
<Form>
<Picker
style={{ width: 200, height: 40 }}
iosHeader="Branch"
Header="Branch"
mode="dropdown"
textStyle={{ color: 'grey' }}
placeholder='Select branch'
headerBackButtonText='Geri'
selectedValue={this.state.selectedBranch}
onValueChange={(value) => this.onBranchSelected(value)}
>
{this.state.branches.map((branches, i) => {
return (
<Picker.Item label={branches.address_line} value={branches.id} key={i} />
);
}
)}
</Picker>
</Form>
</Content>
</Container>
);
}
}
Dependencies
"native-base": "2.3.5",
"react": "16.0.0",
"react-native": "0.50.0",
This is known issue with Picker. The issue is trying to use .map. I myself couldn't ever get map to work with Picker. The only thing I could find was an npm package called react-native-smart-picker which I was able to use a .map with. There are limitations.
And FYI I also tried other bootstrap frameworks and this is an issue with vanilla react-native.
Heres the link..
https://www.npmjs.com/package/react-native-smart-picker
Heres my github repo...
https://github.com/GavinThomas1192/motoMechanicMeeKanic/blob/master/App/Components/vehicleMakePicker.js
Heres my code where I implemented it.
<ScrollView>
<View style={{ flex: 1, marginTop: 20 }}>
{this.state.makes.length > 1 ?
<ScrollView>
<SmartPicker
expanded={this.state.expanded}
selectedValue={this.state.selectedMake}
label='Select Make'
onValueChange={this.handleChange.bind(this)}>
{
this.state.makes.map((ele) => {
return (<Picker.Item label={ele} value={ele}/>);
})
}
<Picker.Item label='Select Make' value='Toyota'/>
</SmartPicker>
<Button block onPress={() => this.props.vehicleMake(this.state.selectedMake)}>
<Text>Done</Text>
</Button>
</ScrollView> : <Spinner/>
}
</View>
</ScrollView>
Update to show how I handled no expandable button
<Content>
<Text>Vehicle Stats:</Text>
<Text>Year: {this.state.vehicleYear}</Text>
<Text>Make: {this.state.vehicleMake}</Text>
<Text>Model: {this.state.vehicleModel}</Text>
{this.state.vehicleYear === "" ? <VehicleYearPicker vehicleYear={this.yearPicked}/> : undefined}
{this.state.vehicleYear !== "" && this.state.vehicleMake === "" ?
<VehicleMakePicker pickedYear={this.state.vehicleYear} vehicleMake={this.makePicked}/> : undefined}
{this.state.vehicleModel === "" && this.state.vehicleMake !== "" ?
<VehicleModelPicker homeState={this.state} vehicleModel={this.modelPicked}/> : undefined}
</Content>

this.props.navigation is undefined when using DrawerNavigator

I'm integrating DrawerNavigator of 'react-navigation' to my project as this document. But when I run the project it always get this error when click on the Button:
TypeError: undefined is not an object (evaluating
'this.props.navigation.navigate')
And when I swipe from left to right, nothing happen, no drawer open.
I've check this.props and it's always log empty {} in console.
I tried many solutions but it's still not working.
calculator.js
export default class Calculator extends Component {
constructor(props) {
super(props);
}
static navigationOptions = {
drawerLabel: 'Calculator',
drawerIcon: ({ tintColor }) => (
<Image
source={require('./../../res/images/icon_calculator.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<View style={styles.container}>
<View>
<Text style={styles.title}>Tip Calculator</Text>
</View>
<Button
onPress={() => this.props.navigation.navigate("SettingsScreen")}
title="Go to settings"
/>
</View>
);
}
}
module.exports = Calculator;
settings.js
export default class Settings extends Component {
constructor(props) {
super(props);
}
static navigationOptions = {
drawerLabel: 'Settings',
drawerIcon: ({ tintColor }) => (
<Image
source={require('./../../res/images/icon_settings.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<View style={styles.container}>
<Text>Settings</Text>
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
</View>
);
}
}
module.exports = Settings;
navigation.js
import {
DrawerNavigator
} from 'react-navigation';
import Calculator from './../components/calculator/calculator.js';
import Settings from './../components/settings/settings.js';
const RootDrawer = DrawerNavigator({
CalculatorScreen: {
path: '/',
screen: Calculator
},
SettingsScreen: {
path: '/sent',
screen: Settings
}
}, {
initialRouteName: 'CalculatorScreen',
drawerPosition: 'left'
});
export default RootDrawer;
App.js
export default class App extends Component<{}> {
render() {
return (
<Calculator/>
);
}
}
index.js
import { AppRegistry } from 'react-native';
import App from './App';
AppRegistry.registerComponent('rn_tip_calculator', () => App);
Do I have to use StackNavigator with DrawerNavigator, or am I missed something in config?
Full source code, it's only a simple example project, please have a look: https://github.com/HCMUS-IceTeaViet-SE/rn_tip_calculator
Any help will be appreciated. Thanks!
You can use dispatch api https://reactnavigation.org/docs/navigators/navigation-actions
1) import navigation actions
import { NavigationActions } from 'react-navigation'
2) dispatch navigation action:
const navigateAction = NavigationActions.navigate({
routeName: 'SettingsScreen',
params: {},
})
this.props.navigation.dispatch(navigateAction)
I'm pretty new to React-Native but sometimes this also happens to me.
I'm using Redux and stack navigator.... but here is my working example...
import { StackNavigator } from 'react-navigation'
import { Animated, Easing } from 'react-native'
import LoginScreen from '../Containers/LoginScreen'
import LaunchScreen from '../Containers/LaunchScreen'
import HomeScreen from '../Containers/HomeScreen'
import SignUpScreen from '../Containers/SignUpScreen'
import SettingsScreen from '../Containers/SettingsScreen'
import VehicleCreateScreen from '../Containers/VehicleCreateScreen'
import styles from './Styles/NavigationStyles'
// Manifest of possible screens
const PrimaryNav = StackNavigator({
LoginScreen: { screen: LoginScreen },
LaunchScreen: { screen: LaunchScreen },
HomeScreen: { screen: HomeScreen },
SignUpScreen: { screen: SignUpScreen },
SettingsScreen: { screen: SettingsScreen },
VehicleCreateScreen: { screen: VehicleCreateScreen }
}, {
// Default config for all screens
headerMode: 'none',
initialRouteName: 'LaunchScreen',
navigationOptions: {
headerStyle: styles.header
},
transitionSpec: {
duration: 0,
timing: Animated.timing,
easing: Easing.step0,
},
},
)
export default PrimaryNav
And then from a component not connected to REDUX
import React, { Component } from 'react';
import { Container, Content, List, ListItem, Icon, Text, Button, Left, Right, Badge } from 'native-base';
import { Image } from 'react-native'
import styles from './Styles/SideBarStyle';
// import backgroundImage from '../Images/vw.jpg'
const backgroundImage = require("../Images/vw.jpg");
const drawerImage = require("../Images/dirtyHandsDark.jpg");
export default class SideBar extends Component {
constructor(props) {
super(props);
}
render() {
// *********** HERE WE DECLARE AN ARRAY TO RENDER LISTS FROM. THIS COULD ALSO BE LIST OF BIKES FROM STORE.. ***********
const datas = [
{
name: "Home",
route: "HomeScreen",
icon: "settings",
bg: "#C5F442",
},
{
name: "Repair",
route: "HomeScreen",
icon: "settings",
bg: "#C5F442",
},
{
name: "My Profile",
route: "SettingsScreen",
icon: "settings",
bg: "#C5F442",
},
];
return (
<Container>
<Content bounces={false} style={{ flex: 1, backgroundColor: "#fff", top: -1 }}>
<Image source={backgroundImage} style={styles.drawerCover}>
<Image square style={styles.drawerImage} source={drawerImage} />
</Image>
<List
dataArray={datas}
renderRow={data =>
// *********** CREATE NEW LIST ITEM ON CLICK NAVIGATE TO APPROPRIATE LISTITEM.SCREEN ***********
<ListItem button noBorder onPress={() => this.props.navigation.navigate(data.route)}>
<Left>
<Icon active name={data.icon} style={{ color: "#777", fontSize: 26, width: 30 }} />
<Text style={styles.text}>
{data.name}
</Text>
</Left>
{data.types &&
<Right style={{ flex: 1 }}>
<Badge
style={{
borderRadius: 3,
height: 25,
width: 72,
backgroundColor: data.bg,
}}
>
<Text style={styles.badgeText}>{`${data.types} Types`}</Text>
</Badge>
</Right>}
</ListItem>}
/>
</Content>
</Container>
);
}
}
You can see I reference this.props.navigation.navigate no problem.
Heres my repo for reference.
https://github.com/GavinThomas1192/motoMechanicMeeKanic/tree/master/App
This happen because I don't "connect" my DrawerNavigator to my app.
There is 2 ways to achieve this:
First way: register DrawerNavigator as app root component. In index.js change:
from AppRegistry.registerComponent('rn_tip_calculator', () => App);
to AppRegistry.registerComponent('rn_tip_calculator', () => RootDrawer);
So you could delete App.js because it's useless now.
Second way: Keep register App component (in App.js) as app root component. Then put inside App component to "connect" DrawerNavigator to the app.
export default class App extends Component<{}> {
render() {
return (
<RootDrawer/>
);
}
}
The document say nothing about how to connect the navigator to the app, nothing about register component or put navigator inside root component. This drive newbie like me mad!

NativeBase : Navigate to a screen inside a Tab (KitchenSink)

I'm using the NativeBase (and especially the NativeBaseSink template). All my routes are defined in the App.js like this :
App.js
import { Platform } from "react-native";
import { Root } from "native-base";
import { StackNavigator, TabNavigator } from "react-navigation";
import Drawer from "./Drawer";
import Homepage from "./main_scenes/main";
import Splashscreen from "./main_scenes/home/";
import LoginScene from "./main_scenes/home/login/";
import RegisterScene from "./main_scenes/home/register/";
import InsertPhoneCode from "./main_scenes/home/pin/";
import MyResults from "./main_scenes/results/";
import MyMap from "./main_scenes/results/map/";
import UserDetails from "./main_scenes/profile/";
import MyResultsByDistance from "./main_scenes/results/Distance"
import MyResultsByAvis from "./main_scenes/results/Avis"
import Test from "./main_scenes/tab"
const AppNavigator = StackNavigator(
{
Drawer: { screen: Drawer },
RegisterScene: {screen : RegisterScene},
Splashscreen:{ screen : Splashscreen},
Homepage:{ screen : Homepage},
InsertPhoneCode:{screen:InsertPhoneCode},
LoginScene: {screen : LoginScene},
MyResults: {screen:MyResults},
MyMap:{screen:MyMap},
UserDetails:{screen:UserDetails},
MyResultsByDistance:{screen:MyResultsByDistance},
MyResultsByAvis:{screen:MyResultsByAvis},
},
{
initialRouteName: "Splashscreen",
headerMode: "none",
}
);
export default () =>
<Root>
<AppNavigator />
</Root>;
I'm using the Tabs functionality of Nativebase framework. Then, I have create an index.js where i've define all my tabs like this :
index.js
import React, { Component } from "react";
import {Dimensions, AppRegistry, StyleSheet,
ListView, ScrollView,View,Image,TouchableOpacity,AsyncStorage, Alert} from 'react-native';
import {
Container,
Header,
Title,
Button,
Icon,
Tabs,
Tab,
Text,
Right,
Left,
Body,
TabHeading,
Footer,
FooterTab,
} from "native-base";
import DisplayByDistance from "./Distance/";
import DisplayByAvis from "./Avis/";
import styles from "./styles";
import { StackNavigator } from 'react-navigation';
export default class ConfigTab extends Component {
constructor(props) {
super(props);
this.state = {
tab1: false,
mapRegion: null,
lastLat: null,
lastLong: null,
};
}
toggleTab1() {
this.setState({
tab1: true,
});
}
render() {
return (
<Container>
<Header hasTabs>
<Left>
<Button transparent onPress={() => this.props.navigation.goBack()}>
<Icon name="arrow-back" />
</Button>
</Left>
<Body style={{ flex: 3 }}>
<Title> Résultats</Title>
</Body>
<Right />
</Header>
<Tabs style={{ elevation: 3 }}>
<Tab
heading={
<TabHeading><Icon name="navigate" /><Text
style={styles.TabTitle}>Le plus prés</Text></TabHeading>
}
>
<DisplayByDistance />
</Tab>
<Tab heading={<TabHeading><Icon name="star-half" /><Text
style={styles.TabTitle}>Le mieux noté</Text></TabHeading>}>
<DisplayByAvis />
</Tab>
</Tabs>
<Footer>
<FooterTab>
<Button active={this.state.tab1} onPress={() => this.props.navigation.navigate("MyMap")}>
<Icon active={this.state.tab1} name="paper-plane" />
<Text>Afficher la carte</Text>
</Button>
</FooterTab>
</Footer>
</Container>
);
}
}
AppRegistry.registerComponent('ConfigTab', () => ConfigTab);
According to the files i've edited, when i press on the TabOne, it opens the right tab where the content is located in the file called Distance.js
So right now, everything works well except that the "props.navigation.navigate"is not recognized in my Distance.js file.
Here is my file
Distance.js
import React, { Component, PropTypes } from "react";
import {...} from 'react-native';
import {...} from "native-base";
import styles from "./../styles";
import { StackNavigator } from 'react-navigation';
import App from "./../../../App"
var productArray = [];
class TabOne extends Component {
constructor(props){
super(props)
var dataSource = new ListView.DataSource({rowHasChanged:(r1,r2) => r1.guid != r2.guid});
this.state={
data:[],
dataSource: dataSource.cloneWithRows(productArray),
isLoading:true,
}
this.donePressed=this.donePressed.bind(this);
};
componentDidMount()
{
this.getTheData(function(json){
productArray = json;
this.setState({
dataSource:this.state.dataSource.cloneWithRows(productArray),
isLoading:false
})
}.bind(this));
}
donePressed() {
const { navigate } = this.props.navigation;
navigate('UserDetails');
}
getTheData(callback) {
var url = "http://paradox.ma/workshop/webservices/getPOI_info.php";
fetch(url)
.then(response => response.json())
.then(json => callback(json))
.catch(error => alert("Erreur de connexion Internet") );
}
list(rowData) {
if (rowData === null) { return <View></View>; };
let VerifiedUser;
const VerifiedTest=rowData.Verified;
if (VerifiedTest==='1')
{
VerifiedUser=(
<Right>
<View style={styles.avatarBox}>
<Text numberOfLines={2}><Icon name="verified" size={30} color="green" /></Text>
<Text>Profil vérifié</Text>
</View>
</Right>
)}
return (
<ListItem thumbnail
onPress={() => this.donePressed().bind(this)}
>
<Left>
<View style={styles.avatarBox}>
<Thumbnail size={55} source={{uri:rowData.Avatar}} />
<Text style={styles.avatarTitle}>{rowData.Title}</Text>
</View>
</Left>
<Body>
<Text>{rowData.Title}</Text>
<Text numberOfLines={2}><Icon name="map-marker" size={15} color="grey" /> {rowData.Address}, {rowData.City} ({rowData.Distance} km)</Text>
<Text numberOfLines={3}>{rowData.Description}</Text>
</Body>
{VerifiedUser}
</ListItem>
);
}
render(){
return(
<Container>
<View>
<TouchableOpacity onPress={() => this.donePressed().bind(this)}>
<Text>Test</Text>
</TouchableOpacity>
</View>
</Container>
);
}
}
export default TabOne;
My function called donePressed() works very well when i replace the this.props.navigation.navigate by alert("Hello") But once I try to navigate between screens, I have an error : Undefined is not an object...this_2.props.navigation.navigate().
I really don't know where is the problem coming from. I have tried to define the function in the constructor, no way.
Hope to find a solution.
if you want to react navigation to inject navigation prop you'll need to declare that specific Component as a Navigator scene
but I would totally suggest using React navigation's TabNavigator,
you can find here how to nest Navigators: https://reactnavigation.org/docs/intro/nesting

Categories

Resources