How to setState in AsyncStorage block with react native? - ios

I want setState in AsyncStorage block but there is a error: undefined is not an object(evaluating 'this.setState').
constructor(props){
super(props);
this.state={
activeID:this.props.data.channel[0].id
};
}
componentDidMount() {
AsyncStorage.getItem(this.props.data.type,function(errs,result){
if (!errs) {
if (result !== null) {
this.setState({activeID:result});
}
}
});
}
_buttonPressed = (id,name,index) => {
this.setState({activeID:id});
AsyncStorage.setItem(this.props.data.type,id,function(errs){
if (errs) {
console.log('error');
}
if (!errs) {
console.log('succeed');
}
});
}
Any help will be appreciate, thanks.

This is a binding issue. Try the following:
componentDidMount() {
AsyncStorage.getItem(this.props.data.type, (errs,result) => {
if (!errs) {
if (result !== null) {
this.setState({activeID:result});
}
}
})
}
The reason for this is that functions declared with the function specifier create a context of their own, that is, the value of this is not the instance of your component. But "fat arrow" functions do not create a new context, and so you can use all methods inside. You could as well bind the function in order to keep the context, but in this case I think that this solution is much cleaner.

I find another solution, but martinarroyo's answer is much more cleaner.
componentDidMount() {
this._loadInitialState().done();
}
async _loadInitialState(){
try{
var value=await AsyncStorage.getItem(this.props.data.type);
if(value!=null){
this._saveActiveID(value);
}
} catch(error){
}
}
_saveActiveID(id) {
this.setState({activeID: id});
}

Related

Susbcribe to many promises?

I'm new to angular and I'm facing a problem where I need to call several promises and get all their results prior to continue the process.
// Let's assume this array is already populated
objects: any[];
// DB calls
insertObject(obj1: any): Promise<any> {
return this.insertDB('/create.json', obj1);
}
updateObject(obj: any): Promise<any> {
return this.updateDB('/update.json', obj);
}
// UI invokes this:
save(): void {
this.insertObject(objects[0])
.then((result) => {
console.log(result.data[0].id);
})
.catch((reason) => {
console.debug("[insert] error", reason);
});
this.insertObject(objects[1])
.then((result) => {
console.log(result.data[0].id);
})
.catch((reason) => {
console.debug("[insert] error", reason);
});
this.updateObject(objects[1])
.then((result) => {
console.log(result.data[0].status);
})
.catch((reason) => {
console.debug("[update] error", reason);
});
//I need to catch these 3 results in order to perform the next action.
}
Any ideas on how to achieve that?
Using the syntax Promise.all(iterable), you can execute an array of Promises. This method resolves when all promises have resolved and fails if any of those promises fail.
This can help you
let firstPromise = Promise.resolve(10);
let secondPromise = Promise.resolve(5);
let thirdPromise = Promise.resolve(20);
Promise
.all([firstPromise, secondPromise, thirdPromise])
.then(values => {
console.log(values);
});

is it possible to lazily use JS libs with Dart?

I am using chartjs (with the dart interface https://pub.dartlang.org/packages/chartjs) and trying to make it deferred by injecting a <script src="chartjs.js"></script> into the head section and awaiting it's load event to then use the lib.
I am getting this exception: Cannot read property 'Chart' of undefined.
It does not happen when the script is within the head of the html before dart.
So, is it possible to load a JS lib after Dart loaded?
this is a problem in DDC.
It addeds require.js to the HTML and conflicts with other libs.
https://github.com/dart-lang/sdk/issues/33979
The solution I've found is to manually remove the header section that uses requirejs from the third-party lib you want to use.
For example, take chartjs: https://cdn.jsdelivr.net/npm/chart.js#2.8.0/dist/Chart.js
You remove this two lines:
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(function() { try { return require('moment'); } catch(e) { } }()) :
typeof define === 'function' && define.amd ? define(['require'], function(require) { return factory(function() { try { return require('moment'); } catch(e) { } }()); }) :
Then the file can be lazily added to the DOM without conflicts.
This is my code to lazily fetch scripts:
class ClientUtils {
static final _scriptFetched = <String, Future<bool>>{};
static ScriptElement _scr(String url) => new ScriptElement()
..async = true
..type = 'text/javascript'
..src = url;
static Future<bool> fetchScript(String url,
{String contextCheck}) async {
bool shouldCheck = contextCheck?.isNotEmpty == true;
hasContext() => js.context.hasProperty(contextCheck) &&
js.context[contextCheck] != null;
if (shouldCheck && hasContext())
return true;
if (!_scriptFetched.containsKey(url)) {
Completer<bool> c = new Completer<bool>();
if (!shouldCheck) {
ScriptElement s = _scr(url)
..onLoad.forEach((Event e) {
c.complete(true);
});
document.body.children.add(s);
} else {
Timer.periodic(Duration(milliseconds: 300), (t) {
if (hasContext()) {
t.cancel();
}
c.complete(true);
});
document.body.children.add(_scr(url));
}
_scriptFetched[url] = c.future;
}
return _scriptFetched[url];
}
}
found a better way!
lets remove the define variable after dart loads, then any third-party lib works when added async :D
add this to your main():
import 'dart:js';
void main() {
context.callMethod('fixRequireJs');
}
and in your index.html:
<script type="text/javascript">
window.fixRequireJs = function()
{
console.log('define is ', typeof define);
if (typeof define == 'function') {
console.log('removing define...');
delete define;
window.define = null;
}
}
</script>
You can try the deferred as syntax:
import 'package:chartjs/chartjs.dart' deferred as chartjs;
void main() {
chartjs.loadLibrary().then(() { ... });
}

Why is this callback being shown as null in this dart method

So I have this code in my flutter app - here the function refreshState is being called by the method foo which is passing in a lambda.However during debugging it says the callback is null. Any ideas why this is happening because of this my callback code is not being executed.
void refreshState(Function callback)
{
if(isAlive) {
setState(() {
if (callback != null) {
callback;
}
});
}
}
at one point in my code I am doing this
void didPush() {
foo();
}
void foo()
{
refreshState(() { //<------------------This lambda is showing up as null in the paramter of refreshState
isBusy = true;
});
}
Any ideas of why this lamda is showing up as null in the refreshState function parameter ?
You misunderstand the debug view here. It is a function () returning (=>) null. You just do not execute it.
() => ...
This is just a shortcut for:
() {
return ...
}
To execute your callback you need to add parantheses though. That would be:
setState(() {
if (callback != null)
callback();
});

Angular2 injected service going undefined

I was following this tutorial and reached the below code with searches wikipedia for a given term. The below code works fine and fetches the search result from wikipedia.
export class WikiAppComponent {
items: Array<string>;
term = new Control();
constructor(public wikiService: WikiService) { }
ngOnInit() {
this.term.valueChanges.debounceTime(400).subscribe(term => {
this.wikiService.search(term).then(res => {
this.items = res;
})
});
}
}
But when I refactored the and moved the code for search to a separate function it is not working. this.wikiService inside the search function is going undefined. Can you throw some light on why it is going undefined?
export class WikiAppComponent {
items: Array<string>;
term = new Control();
constructor(public wikiService: WikiService) { }
search(term) {
this.wikiService.search(term).then(res => {
this.items = res;
});
}
ngOnInit() {
this.term.valueChanges.debounceTime(400).subscribe(this.search);
}
}
You are having a scope issue, "this" inside your callback is not refering to your page. Change your function callback like this:
this.term.valueChanges.debounceTime(400).subscribe(
(term) => {
this.search(term);
});

q.js automatically propagate errors (catch async thrown errors)?

i would like to know if there's any way to automatically propagate errors from a promise to another? IE: catch the thrown error from a nested promise.
for example, in the following code sample, the "internalWorker" nested promise function needs
.fail(function (error) {
return deferred.reject(error);
});
in order to propagate the error. if this line isn't contained, the error is throw to the top. (crashed app)
would it be possible to automatically propagate the error so i don't need to add .fail() functions to all my nested promises?
```
function top(input) {
var deferred = q.defer();
internalWorker(input).then(function (value) {
logger.inspectDebug("top success", value);
}).fail(function (error) {
return deferred.reject(error);
});
return deferred.promise;
}
function internalWorker(input) {
var deferred = q.defer();
q.delay(100).then(function () {
throw new Error("internal worker async error");
}).fail(function (error) {
return deferred.reject(error);
});
return deferred.promise;
}
top("hello").then(function (value) {
logger.inspectDebug("outside success", value);
}).fail(function (error) {
logger.inspectDebug("outside fail", error);
}).done();
```
If you are using https://github.com/kriskowal/q, this will do what you intend:
function top(input) {
return internalWorker(input).then(function (value) {
logger.inspectDebug("top success", value);
return value;
});
}
function internalWorker(input) {
return q.delay(100).then(function () {
throw new Error("internal worker async error");
return value;
});
}
top("hello").then(function (value) {
logger.inspectDebug("outside success", value);
}, function (error) {
logger.inspectDebug("outside fail", error);
}).done();
Return promises or values from within callbacks. Errors propagate implicitly.

Resources