How to send bearer token as parameter and retrieve it in another screen in React Native - react-native

I want to send bearer token as parameter from one screen and retrieve it another screen and send it too sidebar.
Login.js where i have saved bearer token in const usertoken but can't figure out how to sent it as parameter
import React from 'react';
import {Button,Text,View,Image,TextInput,SafeAreaView,ImageBackground,Alert} from 'react-native';
export default class Login extends React.Component{
constructor(props) {
super(props)
this.state = {
UserName: '',
UserPassword: ''
}
}
UserLoginFunction = () =>{
const { UserName } = this.state ;
const { UserPassword } = this.state ;
fetch('https://api.idepoz.com/ncl/api/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: UserName,
password: UserPassword
})
}).then((response) => response.json())
.then((responseJson) => {
//console.log(responseJson);
if(responseJson)
{
const usertoken = responseJson.token;
this.props.navigation.navigate({routeName:'QrScan'});
}
else{
Alert.alert(responseJson);
}
}).catch((error) => {
console.error(error);
});
}
}
The following is the screen where i want to retrieve the parameter and navigate it to sidebar
import React from 'react';
import { Container, Header, Title, Drawer, Content, Footer, FooterTab, Button, Left, Right, Body, Text } from 'native-base';
import { Alert } from 'react-native';
import { MaterialIcons } from '#expo/vector-icons';
import { Ionicons } from '#expo/vector-icons';
import SideBar from './components/SideBar';
export default class QrScan extends React.Component{
closeDrawer = () => {
this.drawer._root.close();
}
openDrawer = () => {
this.drawer._root.open();
}
render()
{
return(
<Drawer
ref={(ref) => { this.drawer = ref; }}
content={<SideBar navigator={this.navigator} closeDrawer={this.closeDrawer}/>}
onClose={() => this.closeDrawer()} >
<Container>
<Header>
<Left>
<Button transparent onPress={this.openDrawer.bind(this)}>
<MaterialIcons name="list" size={40} color="#FFFFFF" />
</Button>
</Left>
<Body>
<Title></Title>
</Body>
<Right>
<Button transparent>
<Ionicons name="search" size={40} color="#FFFFFF" onPress={() => Alert.alert('Search Button pressed')} />
</Button>
</Right>
</Header>
<Content>
<Text>
</Text>
</Content>
</Container>
</Drawer>
);
}
}
This is the sidebar.js where i want to retrieve the token and use it to logout
import React from 'react';
import { Text, Alert } from 'react-native';
import { Drawer,Container, Content, Header, Right, Button } from 'native-base';
import { FontAwesome } from '#expo/vector-icons';
export default class SideBar extends React.Component {
render() {
return (
<Container>
<Header>
<Right>
<Button transparent>
<FontAwesome name="close" size={24} color="#FFFFFF" onPress={() => this.props.closeDrawer()} />
</Button>
</Right>
</Header>
<Content>
<Button transparent>
<Text style={{fontSize: 24}}>Log Out</Text>
</Button>
</Content>
</Container>
);
}
}
This is a expo project and i am using react navigation 4.4.3.

you can use redux for sharing data from one component to another
https://react-redux.js.org/introduction/basic-tutorial

I found the answer, In Login.js I stored the bearer token inside UserLoginFunction
UserLoginFunction = () =>{
const { UserName } = this.state ;
const { UserPassword } = this.state ;
fetch('https://api.idepoz.com/ncl/api/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: UserName,
password: UserPassword
})
}).then((response) => response.json())
.then((responseJson) => {
if(responseJson)
{
this.props.navigation.navigate('QrScan',{usertoken:responseJson.token});
}
else{
Alert.alert(responseJson);
}
}).catch((error) => {
console.error(error);
});
}
In qrscan.js i retrieved the bearer token like this
constructor(props) {
super(props)
this.state = {
token: ''
}
}
componentDidMount(){
this.setState({
token: this.props.navigation.state.params.usertoken,
})
}
Then i send the token again to sidebar like this inside render
render()
{
// const authtoken= this.props.navigation.getParam('usertoken');
//console.log(this.state.token);
return(
<Drawer
ref={(ref) => { this.drawer = ref; }}
content={<SideBar navigator={this.navigator} closeDrawer={this.closeDrawer} usertoken={this.state.token} />}
onClose={() => this.closeDrawer()} >
<Container>
</Container>
</Drawer>
);
}
I retrieved the bearer token in sidebar like this
render() {
console.log(this.props.usertoken);
return ()
}

Related

How to separate API call using react natives context API?

I am new to react native. I have following component in my project for now I have written for fetching API in same component but want to separate it out. I am getting difficulty for how can i access variable which I am using in "getAlbum" method from outside of component.
I am trying to do this using new concept context API . is this possible using context API and how?
Is there standard way to separate API call from component?
import React, { Component } from 'react';
import {
FlatList, Text, View, Image, TouchableOpacity,
} from 'react-native';
import { ActivityIndicator, Provider } from 'react-native-paper';
import axios from 'axios';
import styles from '../style/ThumbnailView.component.style';
import ErrorAlert from '../common/ErrorAlert';
import * as myConstant from '../common/Constants';
export default class HomeScreen extends Component {
// For to Navigation header
static navigationOptions = () => ({
headerTitle: 'Album Information',
});
constructor(props) {
super(props);
this.state = {
isLoading: true,
apiLoadingError: false,
};
}
getAlbums() {
const { navigation } = this.props;
const albumId = navigation.getParam('albumID', 'no data');
axios
.get(
myConstant.API + `photos?albumId=${albumId}`, {timeout: myConstant.TIMEOUT}
)
.then((response) => {
this.setState({
isLoading: false,
dataSource: response.data,
});
})
.catch(err => {
this.setState({isLoading: false, apiLoadingError: true})
});
}
componentDidMount() {
this.getAlbums();
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, paddingTop: 30 }}>
<ActivityIndicator animating={true} size='large' />
</View>
);
}
if (this.state.apiLoadingError) {
return (
<ErrorAlert />
);
}
return (
<React.Fragment>
<Provider>
<View style={styles.listContainer} >
<FlatList
testID='flatlist'
data={ this.state.dataSource } numColumns={3}
renderItem={({ item }) => <View style={styles.listRowContainer}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('AlbumDetailsViewScreen', {
albumTitle: item.title, albumImg: item.url
})} style={styles.listRow}>
<View style={styles.listTextNavVIew}>
<Image source = {{ uri: item.thumbnailUrl }} style={styles.imageViewContainer} />
</View>
</TouchableOpacity>
</View>
}
keyExtractor = { (item, index) => index.toString() }
/>
</View>
</Provider>
</React.Fragment>
);
}
}

React Native filtering API to retrieve specific data

I'm using Zomato API (https://developers.zomato.com/documentation) and am fairly new to getting data from an API, so far I am able to retrieve categories from the API. However what I want to do is pull category data from a specific city. Here is my code:
APIcall.js
import axios from 'axios';
export const apiCall = async(url)=>{
return await axios.request({
baseURL:"https://developers.zomato.com/api/v2.1/categories",
headers: {
'user-key': "a31bd76da32396a27b6906bf0ca707a2",
},
url : url,
method : 'get'
}).then(async(response) => {
return response.data.categories
}).catch(err => console.log(err))
}
Home.js
export default class HomeScreen extends React.Component {
constructor(props){
super(props);
this.state={
data : []
}
}
async componentDidMount(){
this.setState({
data : await apiCall('')
})
console.log(await apiCall('?cities'))//I tried console logging to see what data I can get all I get is [Error: Request failed with status code 404] undefined
}
render() {
return (
<View>
<FlatList
keyExtractor={item => item.id}
data={this.state.data}
renderItem={({ item }) =>
<Card style={styles.container}>
<Text style={{color:'#000',fontWeight:'bold'}}>{item.categories.name} </Text>
</Card>}
/>
</View>
);
}
}
According to Zomato API documentation, in order to pull category data from a specific city you need to pass city_id as Parameter.
import React, { Component } from 'react';
import { FlatList, ActivityIndicator, Text, View } from 'react-native';
import axios from 'axios';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
data: []
}
}
async componentDidMount() {
let result;
try {
result = await axios.request({
method: 'GET',
url: "https://developers.zomato.com/api/v2.1/categories?city_id=280",
headers: {
'Content-Type': 'application/json',
'user-key': "a31bd76da32396a27b6906bf0ca707a2",
},
})
} catch (err) {
err => console.log(err)
}
this.setState({
isLoading: false,
data: result.data.categories
})
}
render() {
return (
<View>
{
this.state.isLoading ?
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator />
</View> :
<FlatList
keyExtractor={item => item.id}
data={this.state.data}
renderItem={({ item }) =>
<Text>{item.categories.name} </Text>
}
/>
}
</View>
);
}
}
Hope it helps you.

How to deal with delay api response in react native using redux?

Im building a react-native app, which when the user try to signIn, I invoike firebase.CreateUser and then an api from firebase function to create that user in my database (Firebase Real-Time). The problem is that when the componentDidUpdate is executed, I still don't have the result from my firebaseFunction, then my props only update if I tap in screen. I would like to know how to deal with that.
Im using redux.
Follow my code:
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Button, Image,Alert} from 'react-native';
import logo from '../../asserts/logo.png'
import { TouchableOpacity, TextInput } from 'react-native-gesture-handler';
import { Divider,Input} from 'react-native-elements';
import axios from 'axios';
import { connect } from 'react-redux';
import { signupUser} from '../../store/actions/Section/actions';
class Signin extends Component {
state = {
fullName:'',
userName:'',
email:'',
password:'',
confirmPassword:'',
bornDate:'',
State:'',
City:''
};
handleEmailChange = val => {
this.setState({ email:val });
};
handlePasswordChange = val => {
this.setState({ password:val });
};
handleConfirmPasswordChange = val => {
this.setState({ confirmPassword:val });
};
handleNameChange = val => {
this.setState({ fullName:val });
};
handleUserNameChange = val => {
this.setState({ userName:val });
};
handleStateChange = val => {
this.setState({ State:val });
};
handleCityChange = val => {
this.setState({ City:val });
};
handleBornDateChange = val => {
this.setState({ bornDate:val });
};
onSignInUser = () => {
const {email,password} = this.state
if(email=='' || password=='')
return;
this.props.signUp(this.state.fullName,this.state.userName, this.state.email,this.state.password,this.state.confirmPassword,this.state.bornDate,this.state.State,this.state.City);
// this.props.navigation.navigate('User');
};
componentDidUpdate() {
const { idUser, loading,error } = this.props;
console.log(idUser);
console.log('aqui');
if (!loading && error) Alert.alert('Erro', error);
if (!loading && idUser) this.props.navigation.navigate('User');
}
render() {
return (
<View style={styles.container}>
<View style={styles.flexCenter}>
<Image source={logo} style={styles.logoImage}/>
<Text style={styles.logoText} >HomeShare</Text>
<Text style={styles.sublogoText} >SignUp</Text>
</View>
<Divider style={styles.divider} />
<View style={styles.flexButton}>
<View style={styles.inputContainer}>
<Input style={styles.textInput} onChangeText={this.handleNameChange} value={this.state.fullName} placeholder='Nome'/>
<Input style={styles.textInput} onChangeText={this.handleUserNameChange} value={this.state.userName} placeholder='User'/>
<Input style={styles.textInput} onChangeText={this.handleBornDateChange} value={this.state.bornDate} placeholder='Nascimento'/>
<Input style={styles.textInput} onChangeText={this.handleStateChange} value={this.state.State} placeholder='Estado'/>
<Input style={styles.textInput } onChangeText={this.handleCityChange} value={this.state.City} placeholder='Cidade'/>
<Input style={styles.textInput} onChangeText={this.handleEmailChange} value={this.state.email} placeholder='E-mail' keyboardType={'email-address'}/>
<Input style={styles.textInput} onChangeText={this.handlePasswordChange} value={this.state.password} placeholder='Senha' secureTextEntry={true}/>
<Input style={styles.textInput} onChangeText={this.handleConfirmPasswordChange} value={this.state.confirmPassword} placeholder='Confirme sua Senha' secureTextEntry={true}/>
</View>
<TouchableOpacity style={styles.button} activeOpacity={0.5} onPress={this.onSignInUser} >
<View>
<Text style={styles.buttonText}>SignIn</Text>
</View>
</TouchableOpacity>
<Text style={{marginTop:10}}>Ou</Text>
<TouchableOpacity style={styles.button} activeOpacity={0.5} onPress={this.signInUser}>
<View>
<Text style={styles.buttonText}>Entrar com Facebook</Text>
</View>
</TouchableOpacity>
</View>
</View>
);
}
}
const mapStateToProps = ({ section: { restoring, loading, user, error, logged, idUser } }) => ({
restoring: restoring,
loading: loading,
user: user,
error: error,
logged: logged,
idUser: idUser
});
const mapDispatchToProps = {
signUp:signupUser
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Signin);
My Action:
export const signupUser = (fullName,userName, email,password,confirmPassword,bornDate,State,City) => dispatch => { dispatch(sessionLoading());
firebaseService.auth().createUserWithEmailAndPassword(email, password).then(user => {
console.log(user);
firebaseService.auth().currentUser.getIdToken(true).then(function(idToken) {
SectionService.signIn(idToken,fullName,userName, email,password,confirmPassword,bornDate,State,City).then((response) =>{
console.log(response);
dispatch(sessionSetId(response));
}).catch(e=> {
dispatch(sessionError(e));
});
}).catch(function(error) {
dispatch(sessionError(e));
});
})
.catch(error => {
dispatch(sessionError(error.message));
});
A proposed solution is to handle the account creation in the createUser callback and to update it with other data in the cloud function. Alternatively you can set up a listener that looks for the document, which will then be created and the listener will be notified.
I personally create the user doc on the client side because I create it with some data only available on the client, but your use case will be dictate your preferred approach.

How do I fetch data from api based on search of the user in React Native?

The goal is to allow the user to input a keyword into a search bar, store the search word or phrase into a string and send a post request to to the movie server and display the results in a FlatList format.
I'm not skilled in javascript, but so far I was able to store the search input into a variable and confirmed it by console logging the search but using that variable to render and display the results in confusing
import React, { Component } from "react";
import {
View,
Text,
FlatList,
StyleSheet
} from "react-native";
import { Container, Header,Item,Input, Left, Body, Right, Button, Icon,
Title } from 'native-base';
class Search extends Component {
constructor(props) {
super(props);
this.state = {text: ''};
this.state = {
dataSource: []
}
}
renderItem = ({item}) => {
return (
<Text>{item.title}</Text>
)}
componentDidMount() {
const apikey = "&apikey=thewdb"
const url = "http://www.omdbapi.com/?s="
fetch(url + this.state.text + url)
.then((response) => response.json())
.then((responseJson)=> {
this.setState({
dataSource: responseJson.Search
})
})
.catch((error) => {
console.log(error)
})
}
render() {
return (
<Container>
<Header
searchBar rounded
>
<Item>
<Icon name="ios-search" />
<Input
placeholder="Type here to translate!"
onChangeText={(text) => this.setState({text})}
/>
</Item>
<Button
transparent
onPress={()=> {
{console.log(this.state.text)}
}
}
>
<Text>Search</Text>
</Button>
</Header>
<FlatList
style={{flex: 1, width:300}}
data={this.state.dataSource}
keyExtractor={(item, index) => 'key'+index}
renderItem={this.renderItem}
/>
</Container>
);
}
}
export default Search;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
My code is a bit sloppy so please forgive me on that, I'm still new to coding.
The issue is you are fetching data from API on componentDidMount but it will be called only once (when component gets mounted).
So the best way to fix it is
Create a func called fetchData
fetchData(text) {
this.setState({ text });
const apikey = '&apikey=thewdb';
const url = 'http://www.omdbapi.com/?s=';
fetch(url + text + url)
.then(response => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.Search,
});
})
.catch((error) => {
console.log(error);
});
}
In onChangeText, call fetchData
<Input
placeholder="Type here to translate!"
onChangeText={(text) => {
this.fetchData(text);
}}
/>

undefined is not an object( evaluating ''_this.props.navigator.push")

I am trying to navigate to other page when the user login. But i am getting this error and i can't seem to figure out why. I am using working on mac.
I tried using navigatorIOS too, but the problem won't go away. Please help.
import React, { Component } from 'react';
import {AppRegistry,View,Text,Image, StyleSheet,Navigator, AsyncStorage } from 'react-native';
import {
Container,
List,
ListItem,
Content,
Footer,
FooterTab,
Header,
Button,
Icon,
Tabs,
Title,
InputGroup,
Input
} from 'native-base';
import{
Actions,
Scene,
Router
}from 'react-native-router-flux';
import Reg from './Reg'
export default class Log extends Component{
render(){
return(
<Container>
<View style={{alignItems:'center'}}>
<Icon name='ios-contact' style={{fontSize:120}}/>
</View>
<Content style={{flex:1, top:50}}>
<List>
<ListItem>
<InputGroup>
<Icon name='ios-at-outline' style={{color:'#5bc0de'}}/>
<Input
onChangeText={(username) => this.setState({username})}
value={this.state.username} placeholder='Email id' />
</InputGroup>
</ListItem>
<ListItem>
<InputGroup>
<Icon name='ios-lock-outline' style={{color:'#5bc0de'}}/>
<Input onChangeText={(password) => this.setState({password})}
value={this.state.password} placeholder="Password" secureTextEntry />
</InputGroup>
</ListItem>
<Button info style={{alignSelf:'center'}} onPress={this.Log}>
LOGIN
</Button>
</List>
</Content>
</Container>
);
}
constructor(props){
super(props);
this.state = {username: '', password: ''};
console.log();
}
Log = () => {
fetch('http://192.168.0.20:3000/users', {
method : 'POST',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
})
})
.then((response) => response.json())
.then((res) => {
if(res.success=== true){
var username = res.message;
AsyncStorage.setItem('username', username);
this.props.navigator.push({
id: 'Ideas'
});
}else {
alert(res.message);
}
})
.done();
}
}
Could you use the navigate to other page
Actions.()
EX:
Actions.dashboard();
if pass any data
Actions.dashboard({id: 'Ideas'});
import React, { Component } from 'react';
import {AppRegistry,View,Text,Image, StyleSheet,Navigator, AsyncStorage } from 'react-native';
import {
Container,
List,
ListItem,
Content,
Footer,
FooterTab,
Header,
Button,
Icon,
Tabs,
Title,
InputGroup,
Input
} from 'native-base';
import{
Actions,
Scene,
Router
}from 'react-native-router-flux';
import Reg from './Reg'
export default class Log extends Component{
render(){
return(
<Container>
<View style={{alignItems:'center'}}>
<Icon name='ios-contact' style={{fontSize:120}}/>
</View>
<Content style={{flex:1, top:50}}>
<List>
<ListItem>
<InputGroup>
<Icon name='ios-at-outline' style={{color:'#5bc0de'}}/>
<Input
onChangeText={(username) => this.setState({username})}
value={this.state.username} placeholder='Email id' />
</InputGroup>
</ListItem>
<ListItem>
<InputGroup>
<Icon name='ios-lock-outline' style={{color:'#5bc0de'}}/>
<Input onChangeText={(password) => this.setState({password})}
value={this.state.password} placeholder="Password" secureTextEntry />
</InputGroup>
</ListItem>
<Button info style={{alignSelf:'center'}} onPress={this.Log}>
LOGIN
</Button>
</List>
</Content>
</Container>
);
}
constructor(props){
super(props);
this.state = {username: '', password: ''};
console.log();
}
Log = () => {
fetch('http://192.168.0.20:3000/users', {
method : 'POST',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
})
})
.then((response) => response.json())
.then((res) => {
if(res.success=== true){
var username = res.message;
AsyncStorage.setItem('username', username);
this.props.navigator.push({ // Remove this line
id: 'Ideas' // Remove this line
}); // Remove this line
Actions.<pushComponentName>({id: 'Ideas'}) // Add this line
}else {
alert(res.message);
}
})
.done();
}
}