Axios post is not a function - react-native

I am getting error when I call axios.post and immediately catch error: [(0 , _dbExpress.default)(...).post is not a function]
const signup = dispatch => async ({email, password, username}) => {
try {
const response = await dbExpress().post('/signup', {email, password, username});
await AsyncStorage.setItem('token', response.data.token);
dispatch({type: 'signin', payload: response.data.token});
navigate('mainFlow');
} catch (error) {
console.log(error.message);
dispatch({type: 'add_error', payload: 'Something went wrong with sign up'});
}
};
Here is my axios interceptors
dbExpress.interceptors.request.use(
async (config) => {
const token = await AsyncStorage.getItem('token');
console.log("*** inside api")
if (token) {
console.log("*** token exist")
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(err)=>{
console.log("*** reject " + err.message);
return Promise.reject(err);
}
);
export default dbExpress;
Server works perfectly when I test using postman so it can't be the server side problem.
The version of expo and axios as below:
"axios": "^0.27.2",
"expo": "~45.0.0",
I not sure where cause the error as these code works on my other project (same version of expo and axios).
If anyone know the issue please help!! Thanks!

Hry to replace
const response = await dbExpress().post('/signup', {email, password, username});
with
const response = dbExpress.post('/signup', {email, password, username});
As far as we can see, your dbExpress exports an axios instance, not a promise

Related

I only get an exception and not the error message from the server

I am currently programming a small login api and have implemented it with my react native project using axios request. But i have a problem now my server send an error status code with a message but in the react antive app it only comes to an exception with the status code and not with the message. How can I best solve this do I have to take the status code out of the server and just send text back or is there another solution?
My React Native api.js:
import axios from "axios";
import AsyncStorage from "#react-native-community/async-storage";
const instance = axios.create({
baseURL: "http://example.com",
});
instance.interceptors.request.use(
async (config) => {
const token = await AsyncStorage.getItem("token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(err) => {
return Promise.reject(err);
}
);
export default instance;
My React Native api trigger:
const Signup = async ({email, password}) => {
try{
const response = await myApi.post("/api/signup", { email, password });
if (response.data.token){
navigation.navigate('setup');
}else{
setError(response.data);
}
}catch (err){
console.log(err);
setError('Internet Error');
}
}
and my server response
return res.status(400).send({
message: "Email or password incorrect!",
});

axios interceptor blocking api calls in redux saga

I have a react native project in which I'm calling some API's using redux-saga mechanism. Now when I added response interceptor for axios my saga api's are not working anymore. Does any knows how I can fix this?
here is the code for my axios instance class and response interceptor
const getLoggedInUser = async () => {
const savedUser = JSON.parse(
await getDataFromAsyncStorage(APP_CONSTANTS.SAVED_USER)
)
if (savedUser?.user_id != null) {
return savedUser
}
return null
}
const baseapi = axios.create({
baseURL: APP_CONSTANTS.BASE_URL,
headers: {},
})
baseapi.interceptors.request.use(
async (config) => {
const token = await getLoggedInUser()
const userId = token?.user_id
const authToken = token?.token
if (token) {
baseapi.defaults.headers.common['userId'] = token
baseapi.defaults.headers.common['token'] = authToken
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// Response interceptor for API calls
baseapi.interceptors.response.use(
(response) => {
return response
},
async function (error) {
const originalRequest = error.config
if (error.response.status === 403 /* && !originalRequest._retry */) {
return baseapi(originalRequest)
}
return Promise.reject(error)
}
)
This is my saga class code and it fails directly when I add a response interceptor
function* getTopicList(action) {
try {
yield put({type: ACTION_TYPES.START_TOPIC_LIST})
const {payload} = action
const res = yield call(getAllTopicsOfBatch, payload)
if (res?.status == APP_CONSTANTS.SUCCESS_STATUS) {
yield put({
type: ACTION_TYPES.SET_TOPIC_LIST,
payload: {data: res?.data?.topics},
})
} else {
alert('OOPS Something went wrong! Please try again')
yield put({
type: ACTION_TYPES.ERROR_TOPIC_LIST,
payload: 'Something Went Wrong Please Try Again',
})
}
} catch (error) {
console.log('RESPONES error', error)
alert('OOPS Something went wrong! Please try again')
yield put({
type: ACTION_TYPES.ERROR_TOPIC_LIST,
payload: 'Something Went Wrong Please Try Again',
})
}
}
The code looks mostly fine, the only two things I found that are likely causing problems are:
In the request interceptors you are likely wrongly passing the whole token as userId instead of userId
baseapi.defaults.headers.common['userId'] = token // 'token' should be 'userId'
In the response interceptors error handler, you are not guaranteed to have 'response' property on error.
if (error.response.status === 403) // use error?.response
If neither of these things will fix your problem my guess is you have a problem in your endpoint and so you should examine the response errors you get to guide you.

In reactnative expo I tried using secureStore from expo in redux to save token the one I get from api

I tried using redux to save token the one I get from api in react native ..its working now.
First one is for settoken and other one is for gettoken.
enter image description here
export const verifyOTP = (formValues, actions) => {
return async (dispatch) => {
dispatch(startSubmitting());
const url = `/validate-otp`;
var formdata = new FormData();
formdata.append("mobile", formValues.mobile);
formdata.append("otp", formValues.otp);
const response = await api.post(url, formdata);
dispatch({
type: "VERIFY_OTP",
payload: response,
});
dispatch(stopSubmitting());
await SecureStore.setItemAsync("userToken", response.data.access_token);
};
};
export const checkUser = () => {
return async (dispatch) => {
const token = await SecureStore.getItemAsync("userToken");
const url = `/me`;
const response = await api
.post(url, { token })
.then((res) => {
return res;
})
.catch((error) => {
return error.response;
});
dispatch({
type: "CHECK_USER",
payload: response,
});
};
};
The Problem
you are mixing two different implementations in checkUser to handle a promise which is clearly incorrect and leads to the issues.
The Solution
since your other parts of codes use the async/await so try to remove then/catch block from the response constant:
const checkUser = () => {
return async (dispatch) => {
const url = '/me';
try {
const token = await SecureStore.getItemAsycn("userToken);
const response = await api.post(url, {token})
dispatch({type: "CHECK_USER", payload: response})
} catch (error) {
// to proper action on failure case
}
}
}
Note 1: always use async/await in try/catch block. more on MDN documentation.
Optional
since you are trying to call two async actions (once for getting token and once for calling '/me' API), I encourage you to use two different try/catch blocks to handle the failure case for each async action separately. for example:
const checkUser = () => {
return async (dispatch) => {
let token = null;
try {
token = await SecureStore.getItemAsync("userToken");
} catch (err) {
// proper action in case of failure on getting the token from storage
}
// you may need to ignore API calls without the token, so:
try {
if(token){
const url = '/me';
const response = await api.post(url, {token});
dispatch({type: "CHECK_USER", payload: response});
}
} catch (err) {
// take proper action with the error response according to your applicaiton
}
}
}

How can I console log axios response outside the request

async login(context, payload) {
const response = await axios
.post(
'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyCQ6w2jvJVNrOwON4-KnEOV1kH-ckEDokg',
{
email: payload.email,
password: payload.password,
returnSecuredToken: true
},
{
Headers: {
'Content-Type': 'application/json'
}
}
)
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
console.log(error.response);
});
console.log(response);
context.commit('setUser', {
token: response.data.idToken,
userId: response.data.userId,
tokenExpiration: response.data.expiresIn
});
Hello, maybe it's a dumb question but how can I console.log my response there ? I tried to stock my response in a const but it's the same issue, the console log and the commit execute before the await async and I can't use any data that return from the axios response, thanks if you take the time to help me.
You don't need then function in this case. With await word is enough
The problem is your intermediate .then returns nothing, so the return value of await axios.post() resolves to undefined.
You could either remove the unnecessary .then:
const response = await axios.post(/*...*/);
console.log(response);
...or return response in .then:
const response = await axios.post(/*...*/)
.then(response => {
console.log(response);
return response;
});

IBM IAM IamAuthenticator getToken is not a function

I'm trying to get a token to use IBM Watson Speech-to-Text in my app. Here's my code:
const { IamAuthenticator } = require('ibm-cloud-sdk-core');
const authenticator = new IamAuthenticator({
apikey: 'myApiKey',
});
authenticator.getToken(function (err, token) {
if (!token) {
console.log('error: ', err);
} else {
// use token
}
});
The error message is authenticator.getToken is not a function.
The documentation says:
string IBM.Cloud.SDK.Core.Authentication.Iam.IamAuthenticator.GetToken ( )
I've tried both getToken and GetToken. Same error message. The code isn't complicated, what am I doing wrong?
This is what worked for me with the latest ibm-watson node-sdk,
Install node-sdk with this command
npm install --save ibm-watson
Then, use this code snippet in your app.js or server.js node file to receive the IAM access token
const watson = require('ibm-watson/sdk');
const { IamAuthenticator } = require('ibm-watson/auth');
// to get an IAM Access Token
const authorization = new watson.AuthorizationV1({
authenticator: new IamAuthenticator({ apikey: '<apikey>' }),
url: ''
});
authorization.getToken(function (err, token) {
if (!token) {
console.log('error: ', err);
} else {
console.log('token: ', token);
}
});
You can also directly use the IamAuthenticator with Speech to Text
const fs = require('fs');
const SpeechToTextV1 = require('ibm-watson/speech-to-text/v1');
const { IamAuthenticator } = require('ibm-watson/auth');
const speechToText = new SpeechToTextV1({
authenticator: new IamAuthenticator({ apikey: '<apikey>' }),
url: 'https://stream.watsonplatform.net/speech-to-text/api/'
});
const params = {
// From file
audio: fs.createReadStream('./resources/speech.wav'),
contentType: 'audio/l16; rate=44100'
};
speechToText.recognize(params)
.then(response => {
console.log(JSON.stringify(response.result, null, 2));
})
.catch(err => {
console.log(err);
});
// or streaming
fs.createReadStream('./resources/speech.wav')
.pipe(speechToText.recognizeUsingWebSocket({ contentType: 'audio/l16; rate=44100' }))
.pipe(fs.createWriteStream('./transcription.txt'));
See my answer in your other post that might help. You use BearerTokenAuthenticator if you want to manage the token authentication process yourself.