Hello I tried to set the state on fetch call like this:
getCats() {
fetch(GLOBALS.API + '/specials.php?action=getCats&key=' + GLOBALS.KEY)
.then((response) => response.json())
.then((responseJson) => {
this.setState = ({
dataSource: "test"
});
Alert.alert("test");
})
.catch((error) => {
console.log(error.toString());
});
}
componentDidMount() {
this.getCats();
console.log(this.state.dataSource);
}
but the line:
console.log(this.state.dataSource);
return me undefined
and I get an alert of "test"
what the problem?
tnx a lot
You Can Make Use of callbacks.
Below is the code example
getCats(successCallBack, failureCallback) {
fetch(GLOBALS.API + '/specials.php?action=getCats&key=' + GLOBALS.KEY)
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
failureCallback();
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data)
successCallBack(data);
});
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
failureCallback();
});
}
Below is the code for success and failure call backs
successCallBack(data) {
console.log(data)
}
failureCallback() {
alert("failure");
}
Below is the code to bind success and failure callbacks.
getCats(this.successCallBack.bind(this), this.failureCallback.bind(this));
Fetch is asynchronous so it will return immediately, before the code in the then clauses are run. Therefore, setState will not have run before the console logging.
Related
I am working on react native application and want to integrate the Phone masking feature like Uber do. I have choosen Twilio Phone Masking for this. I have used react-native-twilio-programmable-voice package.
I have integrated this using this link:: https://medium.com/#edzh1/create-a-twilio-voip-calls-in-a-react-native-app-35a729a9613d
I have done server setup successfully, using php. But getting error deviceNotReady error : "Registration failed". I have no idea what I am doing wrong here.
This is initial function I am calling here::
initTwilio = async () => {
const token = await this.getAuthToken();
if (Platform.OS === 'android') {
await this.getMicrophonePermission();
}
const success = await TwilioVoice.initWithToken(token);
if (success.initialized) {
TwilioVoice.addEventListener('deviceReady', () => {
this.setState({ twilioInited: true });
});
TwilioVoice.addEventListener('deviceNotReady', function (data) {
console.log('data', data) // getting error here
});
if (Platform.OS === 'ios') { //required for ios
TwilioVoice.configureCallKit({
appName: 'ReactNativeTwilioExampleApp',
});
}
}
};
getAuthToken = () => {
return fetch('https://myurl/accessToken.php', {
method: 'get',
})
.then(response => response.text())
.catch((error) => console.error(error));
}
Please help, and suggest me what I am doing wrong here.
I have implemented firebase phone authentication mechanism to login user with following
code:
(<any>window).FirebasePlugin.verifyPhoneNumber('+91'+this.phone, 60, function (credential) {
//alert("sms sent successfully"+ credential.verificationId);
//this.verificationId = credential.verificationId;
let modal = this.modalCtrl.create(verificationPage,{verificationId: credential.verificationId});
modal.present();
}, error => {
alert(JSON.stringify(error));
console.log("error: " + error);
});
}
but credential.verificationId value can't able to store or send to another page
verify() {
this.signInCredential = firebase.auth.PhoneAuthProvider.credential(this.verificationId, this.code);
alert("u"+JSON.stringify(this.signInCredential));
firebase.auth().signInWithCredential(this.signInCredential).then((info) => { alert("check"+JSON.stringify(info));}, (error) => {
alert("err"+JSON.stringify(error));})
}
How to resolve above error?
You should get the parameters from the nav params, directly it won't work.
try
constructor(public params: Navparams){
}
verify() {
let verificationId = params.get("verificationId");
this.signInCredential =
firebase.auth.PhoneAuthProvider.credential(verificationId, this.code);
alert("u"+JSON.stringify(this.signInCredential));
firebase.auth().signInWithCredential(this.signInCredential).then((info) =>
{
alert("check"+JSON.stringify(info));}, (error) => {
alert("err"+JSON.stringify(error));
})
}
i hope this will help you.
For your reference check this article
https://medium.com/#gbrigens/ionic-3-phone-authentication-with-firebase-dbed967e95ef
I am getting this this error. As I am already using ES6 format, That arrow but also getting same error. And somewhat confuse that how to use bind. How can I get out of this error.
code:
async fetchData() {
const { navigate } = this.props.navigation;
var DEMO_TOKEN = await AsyncStorage.getItem(STORAGE_KEY);
NetInfo.isConnected.fetch().then((isConnected) => {
if ( isConnected )
{
return fetch(`${url}`,
{
method: "GET",
headers: {
'Authorization': `JWT ${DEMO_TOKEN}`,
}
})
.then(
function(response) {
console.log(response.headers);
console.log(response.status);
console.log(response.url);
if (response.status !== 200) {
console.log('Status Code: ' + response.status);
return;
}
response.json().then((responseData) => {
console.log(responseData);
this.setState({
ver: responseData.results.appversion, // getting error here
});
});
}
)
.catch(function(err) {
console.log('Fetch Error', err);
});
Just to be clear about which this you're trying to reference, could you do this?
async fetchData() {
const ctx = this
And then reference ctx instead of this:
ctx.setState({
ver: responseData.results.appversion,
});
I am quite new to React / React Native / Redux so I feel I am doing something wrong.
The problem
I want to show a spinner while an API is called, and an error message once this API call fails. Props are not updating, and so the components don't show the desired message or spinner
The code (only the relevant chunks)
The component
class Home extends Component {
componentWillMount() {
this.props.tokenGet();
}
renderSpinner() {
if (this.props.loading) {
return (
<Spinner size="large" />
);
}
return null;
}
renderMessage() {
if (this.props.message) {
return (
<Text style={{flex: 1, background: red, color: black}}>
{ this.props.message }
</Text>
)
}
return null;
}
render() {
return (
{ this.renderSpinner() }
{ this.renderMessage() }
)
}
}
const mapStateToProps = (state) => {
const { auth } = state;
const {
loading,
token,
message
} = auth || {
loading: false,
token: null,
message: null
};
return {
loading,
token,
message
}
};
export default connect(mapStateToProps, { tokenGet } )(Home);
The action creator
export const tokenGet = () => {
return (dispatch) => {
dispatch({ type: 'TOKEN_GET_START'});
// Perform the actual API call
let requestToken = fetch(apiBaseUrl + "/tokens", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(.....)
});
Promise
.race([timeout, requestToken])
.then((response) => response.json())
.then((responseJson) => {
... not relevant ...
})
.catch((error) => {
dispatch({ type: 'TOKEN_GET_FAIL', payload: error});
});
The timeout function, which gets called when the server fails to respond
let timeout = new Promise((resolve, reject) => {
setTimeout(reject, 2000, 'Request timed out. Please check your internet connection.');
});
The reducer
import {
TOKEN_GET_START,
TOKEN_GET_SUCCESS,
TOKEN_GET_FAIL
} from '../actions/types';
const INITIAL_STATE = {
loading: false,
token: null,
message: null
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case TOKEN_GET_START:
return { ...state, loading: true };
case TOKEN_GET_SUCCESS:
return { ...state, loading: false, token: action.payload };
case TOKEN_GET_FAIL:
return { ...state, loading: false, message: action.payload };
default:
return state;
}
};
The combined reducers
import { combineReducers } from 'redux';
import AuthReducer from './AuthReducer';
export default combineReducers({
auth: AuthReducer
});
The actual behavior is that the props don't change and no message or spinner is visible. With some console logs I know that the API call ends because of the timeout. I am not sure if the state gets updated properly though. I don't know in at which point I can console log this.
It turned out to be because of the quotes in 'TOKEN_GET_FAIL'
That is a string and not the const I need. So I changed to TOKEN_GET_FAIL and it works.
This question already has an answer here:
Variable not updating with fetch response data in Angular 2 beta
(1 answer)
Closed 6 years ago.
I try to explain in English, but I don't speak it.
I'm working in a Ionic 2. I try to do a http request with post method and I am emulate in SDK Android emulator and I can see in the logcat:
Cannot call method 'post' of undefined at
file:///android_asset/www/build/js/app.bundle.js:2265
But I review and don't see anything, I rewrite my clientId and ClientSecret to can post here. I put a trace console.log(this.http) in the login function and this attribute is undefined, althought is inject in the class' constructor.
My code:
import {Page, Platform} from 'ionic-angular';
import {Http, Headers, HTTP_PROVIDERS} from 'angular2/http';
#Page({
templateUrl: 'build/pages/home/home.html',
providers: [ HTTP_PROVIDERS ]
})
export class HomePage {
static get parameters() {
return [[Platform],[Http]];
}
constructor(platform, http) {
this.platform = platform;
this.http = http;
this.clientId = "clientId";
this.clientSecret = "clientSecret";
}
login() {
this.platform.ready().then(() => {
this.googleLogin().then((success) => {
alert(success.access_token);
}, (error) => {
alert(error);
});
});
}
googleLogin() {
return new Promise(function(resolve, reject) {
var browserRef = window.cordova.InAppBrowser.open("https://accounts.google.com/o/oauth2/auth?client_id=" + "clientId" + "&redirect_uri=http://localhost/callback&scope=email%20profile&approval_prompt=force&response_type=code&access_type=offline", "_blank", "location=no,clearsessioncache=yes,clearcache=yes");
browserRef.addEventListener("loadstart", (event) => {
if ((event.url).indexOf("http://localhost/callback") === 0) {
var headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
var parameters = "client_id=" + "clientId" + "&client_secret=" + "clientSecret" + "&redirect_uri=http://localhost/callback" + "&grant_type=authorization_code" + "&code=" + requestToken
var requestToken = (event.url).split("code=")[1];
this.http.post("https://accounts.google.com/o/oauth2/token", parameters, { header:headers })
.subscribe( data => { resolve(data); },
error => { reject("Problem authenticating with Google"); }
);
browserRef.removeEventListener("exit", (event) => {});
browserRef.close();
}
});
browserRef.addEventListener("exit", function(event) {
reject("The Google sign in flow was canceled");
});
});
}
}
The code tries to authenticate with Google OAuth2, althought the error seems to be in the attributes in the constructor(http, clientId, clientSecret) there are not defined when the login function is called. I don't know what's wrong!
It might have something to do with the scoping of 'this', depending on what calls the googleLogin function.
Try using an arrow function:
googleLogin = () => {
...
}
It's because you don't use an arrow function when defining your promise. So the this keyword doesn't correspond to the instance of the component itself. With arrow functions, you can use the lexical this that will correspond to the component instance.
googleLogin() {
return new Promise((resolve, reject) => {
(...)
});
}
instead of
googleLogin() {
return new Promise(function(resolve, reject) {
(...)
});
}
See this link for more hints about the lexical this of arrow functions:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions.