how to correctly setState in the reactjs function - reactjs

In my case, I want to change the image url to base64 file using the "base64-img" library.
I intend to save the results of converting the file into a state. I tried saving it to a variable also failed. I wrote the script as follows:
var base64Img = require('base64-img');
base64Img.requestBase64('url_image', function(err, res, body) {
this.setState ({ b64:body });
});
I get an error Uncaught TypeError: Cannot read property 'setState' of undefined
I try to set the value to a variable then console_log works well, but the value cannot be accessed from outside.
let b64;
base64Img.requestBase64('url_image', function(err, res, body) {
b64 = body;
console.log(b64);
});
I want to use the value b64 outside of the function. Thanks

You can use ES6 arrow function to call setState and to access b64 outside the function or in custom function, you can bind the function inside the constructor and access using this
const base64Img = require('base64-img');
//convert image to base 64
convertImgtoBase64(imageUrl) {
base64Img.requestBase64(imageUrl,(err, res, body) => {
this.setState ({ b64:body });
});
}
Like this
constructor(props){
super(props);
this.state = {
b64: null
};
this.convertImgtoBase64 = this.convertImgtoBase64.bind(this);
this.showBase64Value = this.showBase64Value.bind(this);
}
showBase64Value(){
console.log(this.state.b64);
}

You used
var base64Img = require('base64-img');
base64Img.requestBase64('url_image', function(err, res, body) {
this.setState ({ b64:body });
});
Here this will indicate the function instance, so that that instance won't contain setState method
So I suggest to try to use like this
var base64Img = require('base64-img');
let _self = this;
base64Img.requestBase64('url_image', function(err, res, body) {
_self.setState ({ b64:body });
});

Related

Extracting a value from Two API calls in ReactJS

How will I get the value from the first API call and use it in the second API call?
var custAcctNum = QueryString.getValue("customer");
ProxyData.getData('/customer/api/customers/' + custAcctNum, (data) => {
this.setState({ dataCust: dataCust });
});
var deviceId =  dataCust.ioTDeviceId;
ProxyData.getData('device/api/devices/' + deviceId, (data) => {
this.setState({ data: data });
});
You can do something like below. Calling the second async function in the callback of first function.
var custAcctNum = QueryString.getValue("customer");
ProxyData.getData('/customer/api/customers/' + custAcctNum, (data) => {
this.setState({ dataCust: dataCust });
var deviceId = dataCust.ioTDeviceId;
ProxyData.getData('device/api/devices/' + deviceId, (data) => {
this.setState({ data: data });
});
});

ReactJS & Flux get data from promise

I am trying to get data from server with service function that I found in a template reactjs project. I do recieve a perfectly fine anwser from the server, I can see the arrays are ok while still in the service, but not when handed over to the component that called for it in the first place. At the component I get a promise object, which has the values (I have seen them in console) but I can't access them. What am I missing?
My component has following function:
calculate(dict) {
var results = Service.calc(dict)
.catch((err) => {
var errResp = JSON.parse(err.response);
console.log(errResp);
this.setState({responseErrors: errResp});
});
this.setState({results:results._handler});
}
When I printed the results in to console I saw the Promise object, inside _handler.handler was a value array with my values but I couldn't use them. The error appeared when accessing the results._handler.handler: undefined.
The called service looks like this:
class Service {
calc(dict) {
return this.handleCalculate(when(request({
url: UserConstants.URL,
method: 'POST',
type: 'json',
data: dict
})));
}
handleCalculate(calcPromise) {
return calcPromise.then(
function(data) {
console.log(data); //Success
return data;
}
)
}
Meanwhile I use ajax call directly in the component instead of the service. But I understand that is bad practice, how can I get this right?
Hi basically you put setState in the wrong place. (It sets state right away without waiting for result getting resolved). It should look like this
calculate(dict) {
var results = Service.calc(dict)
.then(results => {
this.setState({results: results});
})
.catch((err) => {
var errResp = JSON.parse(err.response);
console.log(errResp);
this.setState({responseErrors: errResp});
});
}

React/React Native: Execution order in a Component

I am not able to figure out the sequence of code execution in react native. The following code logs test, test 2 and then test 1. I want to change value of submittedURI.
constructor(props) {
super(props);
this.state = {
enterURI: ''
};
}
onUriTextChanged(event) {
this.setState({ enterURI: event.nativeEvent.text });
}
onSubmitPress() {
var submittedURI = this.state.enterURI;
console.log("test "+submittedURI);
var url = encodeURIComponent(submittedURI), data = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.urlmeta.org/?url=" + url);
xhr.send(data);
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
// console.log(this.responseText);
var responseJSON = JSON.parse(this.responseText);
submittedURI = responseJSON.meta.image;
console.log("test 1 "+submittedURI);
}
});
this.props.onURISubmit(submittedURI);
console.log("test 2 "+submittedURI);
}
The function in the xhr.addEventListner("readystatechange", function() { ... }) is a callback and get's called after the request is DONE. Therefore console.log("test 2 "+submittedURI); is called before the request is completed.
See the docs here (https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/onreadystatechange)
If you want to change submittedURI you are going to have to call this.props.onURISubmit(submittedURI); function within the readystatechange callback. Make sure the callback has the proper context to access this.props.

Firebase React. How can I access my Auth values in React / Webpack?

I'm not sure how to write this question so please let me know if you need any more information.
I'm building an online shop web application. I'm coding the login functionality using Google's Firebase authorisation API.
It logs in fine and inside the: user.getToken().then function, I can console.log the displayName just fine. If it was a static webpage, i could append it to the DOM too.
Inside react/webpack though, I want to set the displayName string as my usernameState state. It doesn't work, when I run this.setState inside the user.getToken().then function, it fires an error, see below.
I would like to be able to use that value on the webpage/react states.
constructor(){
super();
this.state = {
usernameState: ""
};
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var uid = user.uid;
var providerData = user.providerData;
user.getToken().then(function(accessToken) {
console.log(displayName);
this.setState({
usernameState:JSON.stringify(displayName) //cannot read property 'setState' of undefined
});
});
} else {
// User is signed out.
console.log("signed out");
}
}, function(error) {
console.log(error);
});
};
make a bind or save real this
constructor(){
super();
this.state = {
usernameState: ""
};
const self=this;
...
self.setState(...)
...
}

Not returning Restangular back-end call correctly

My back-end call is returning undefined. A.k.a TypeError: Cannot read property 'then' of undefined. I think I am calling it incorrectly.
Here is the AngularJS controller code:
$scope.addUser = function (chaseUser) {
Accounts.addChaseUser(userToSubmit).then(function (response, err) {
if (err) {
$scope.errorMessage = "There was an error.";
$log.debug(err);
} else if (response) {
$scope.errorMessage = "It worked.";
$log.debug(response);
} else {
$scope.errorMessage = "No 'response' nor 'err' returned from backend";
}
});
};
How this responds is that if...
(1) I put in correct credentials, I get a response that comes back with all the transaction data but still TypeError: Cannot read property 'then' of undefined in the console.
(2) Input incorrect credentials, I get no error object, response object, or even making it down to the line where I have $scope.errorMessage = "No 'response' nor 'err' returned from backend"; plus, of course, `cannot read property 'then' of undefined.
Corresponding AngularJS service:
return {
addChaseUser: function(credentials) {
return Restangular.one('user').customPOST(credentials, 'addUser');
}
};
On the backend (controller):
module.exports = {
addChaseUser: function (req, res) {
PlaidService.provideCredentialsToMFA(req.body, function (err, mfaRes) {
if (err) {
return res.status(403).json(err);
}
return res.json(mfaRes);
});
},
};
Backend service:
var plaid = require('plaid');
var plaidClient = new plaid.Client('test_id', 'test_secret', plaid.environments.tartan);
module.exports = {
provideCredentialsToMFA: function (credentials, cb) {
Q.fcall(PlaidService.connectUser.bind(this, credentials))
.then(PlaidService.saveUsersAccessToken.bind(this, credentials))
.then(PlaidService.getTransactionData.bind(this, credentials))
.then(function(transactions) {
cb(null, transactions);
},
function(err) {
console.log(err);
cb(err, null);
});
},
}
How am I supposed to be calling this Restangular POST from the AngularJS controller? It should not be returning undefined.
Since you are getting the response from the server side, it means that your server side code and the angular service code is working just fine. :)
The only possibility I can see is that I is wrong with the application of .then() block is that insted of two parameters(i.e., response and err) lets try with only one parameter.
Something like following :
$scope.addUser = function (chaseUser) {
Accounts.addChaseUser(userToSubmit).then(function (response) {
if(response.status == 'error'){
$log.debug('Got error in the response');
}else{
$log.debug('SUCCESS');
}
});
};
I have used .then(function(data)) with only one parameter. That is the only thing I could find :)
Incase you still don't see it, you are missing a few returns in your functions.
addUser: function (req, res) {
return PlaidService.provideCredentialsToMFA(
// ... your code ...
);
},
provideCredentialsToMFA should return the promise
provideCredentialsToMFA: function (credentials, cb) {
return plaidClient.addConnectUser(
// ... Your code ...
);
}
EDIT:
simplifying the working code looks something like this. Notice there are no returns and only callbacks are used:
findChargeById: function (req, res) {
fetchCharge(someParams, someCallBack);
}
fetchCharge: function (chargeId, cb) {
stripe.charges.retrieve(chargeId, anotherCallBack);
}
Your code looks like this. It's similar but the $scope.addUser expects something returned and doesn't use a callback
addUser: function (req, res) {
provideCredentialsToMFA(someParams, someCallBack);
// addUser returns nothing
}
provideCredentialsToMFA: function (credentials, cb) {
plaidClient.addConnectUser(someParams, someCallBack);
// provideCredentialsToMFA returns nothing and it seems plaidClient.addConnectUser returns nothing too
}
$scope.addUser = function (userInfo) {
// Here is the difference with your 'then' call. Accounts.addUser doesn't return anything and takes 2 params
Accounts.addUser(userInfo).then(someCallBack);
};

Resources