I'm trying to make an singleton Class that uses AsyncStorage.
Follow the code:
import ReactNative, { AsyncStorage } from "react-native";
export default class StorageHandler {
static async getItem(key) {
try {
return await AsyncStorage.getItem(key);
} catch (error) {
console.log(error);
}
}
static async setItem(key, value) {
console.log("Values on StorageHandler", key, value);
try {
await AsyncStorage.setItem(key, value);
} catch (error) {
console.error(error);
}
}
}
I'm using the setItem function in a function in a component, follow the function:
async onIds(device) {
console.log("Device info: ", device);
try {
await StorageHandler.setItem(StorageConstants.ONESIGNAL_ID, device.userId)
} catch (error) {
console.log(error);
}
}
But i'm getting an error :
ReferenceError: value is not defined;
The log on StorageHandler returns :
Values on StorageHandler onesignal_id xxxxx-xxxxx-xxxx-xxxx-xxxxxx
So, what i'm doing wrong ?
And most important, why is it happening?
I'm starting at react-native so i'm a bit lost.
Edit1 :
Removed Resolve from getItem catch.
I deleted the react-native app from my device and recompile without livereload and it worked.
Maybe it's something wrong with livereload.
Edit: The chrome debugger by default have the option "Pause on Exceptions" on.
Sometimes the promises didn't return an error, and by the act of livereload it seems the chrome is pausing the promises doe to the previous error.
Just turn "Pause on Exceptions" off and it work like a charm.
Related
I am using RN 0.61.5, and set my custom error handler ErrorUtils.setGlobalHandler(customHandler);.
export const setGlobalErrorHandler = once(nativeModule => {
console.log("inside setGlobalErrorHandler")
const originalHandler = ErrorUtils.getGlobalHandler();
console.log("originalHandler:", originalHandler)
async function handler(error, fatal) {
if (__DEV__) {
console.log("is dev env")
return originalHandler(error, fatal);
}
console.log("inside setGlobalErrorHandler, is not dev env")
if (!isError(error)) {
console.log("is not error type")
await nativeModule.logPromise(`Unknown Error: ${error}`);
return originalHandler(error, fatal);
}
try {
console.log("create JS error")
const stackFrames = await StackTrace.fromError(error, { offline: true });
await nativeModule.recordErrorPromise(createNativeErrorObj(error, stackFrames, false));
} catch (e) {
console.log("met with error:", JSON.stringify(e));
// do nothing
}
return originalHandler(error, fatal);
}
ErrorUtils.setGlobalHandler(handler);
console.log("newHandler:", ErrorUtils.getGlobalHandler())
return handler;
});
Did a small test by throwing a JS error when a button is clicked, but my customHandler does not get invoked. The app doesn't show an RED color error box nor crashes. I am suspecting that some other places are handling the error. I did implement any ErrorBoundary that catches all uncaught errors
I'm trying to store my users authorization key using AsyncStorage but whenever I do I get weird characters. Here is my relevant code:
async function retrieveItem(key) {
try {
let retrievedItem = await AsyncStorage.getItem(key).then(value => retrieveItem = value);
return retrievedItem;
} catch (error) {
console.log(error.message);
}
return
}
let test = retrieveItem('#authentication')
class AppNavigation extends Component {
render() {
console.log(test)
...
This is the output that I get for test. The item that I want is there under _55 and I'm able to get it by doing console.log(test._55). I just wanted to make sure I am not doing this correctly. Will the key always be _55 for async storage?
{"_40": 0, "_55": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZTk1ODM3NDJlZDI1YjAxMWM4MWFiNWEiLCJpYXQiOjE1ODY4NTY4MjB9.yK0WYuZj7_2Nih7phisi5rmm0y7gF__PMRMEAafIkFk", "_65": 1, "_72": null}
You should note use async/await and .then together, both do the same thing.
Try this code instead:
async function retrieveItem(key) {
try {
let retrievedItem = await AsyncStorage.getItem(key);
return retrievedItem;
} catch (error) {
console.log(error.message);
}
return
}
let test = await retrieveItem('#authentication')
class AppNavigation extends Component {
render() {
console.log(test)
Edit: the object you got is a promise and you can get its value by doing the async/await syntax or calling .then(...)
its actually Promise Pointer you have to resolve the Promise by await
use it in classes
async componentDidMount() {
let test =await retrieveItem('#authentication');
console.log(test);
}
use it in hooks
useEffect(async () => {
let test =await retrieveItem('#authentication');
console.log(test);
});
I am using componentDidUpdate() method for displaying updated data on screen whenever any functionalities is performed like scanning Qr code and storing data. But after searching on net I found that calling this.setState in componentDidUpdate() creates infinite loop. I tried to remove this problem through including prevState in the above method but I failed. Below is my code for more details. How can I update state coming from Asyncstorage without the help of componentDidUpdate()?
componentDidUpdate() {
try {
AsyncStorage.getItem('Data').then((value) => {
this.setState({
list: JSON.parse(value)
})
})
} catch (err) {
}
}
Any help or suggestions would be helpful Thanks.
Updating the state in componentDidUpdate will trigger another componentDidUpdate call, so you should restrict calling setState(). For example:
componentDidUpdate(prevProps, prevState) {
// Only update state if list is empty
if (prevState.list.length === 0) {
try {
AsyncStorage.getItem('Data').then((value) => {
this.setState({
list: JSON.parse(value)
})
})
} catch (err) {
}
}
}
I am using Asyncstorage to store user data like:
try {
await AsyncStorage.setItem(prod_id, '1').then(()=>{
alert('Added to Cart');
});
} catch (error) {
console.log(error);
}
but when I add it to onPress action it takes long time to save data and then my alert is called. Am I doing something wrong? Please I need help!
I think you are mixing two ways of handling the promises in JS.
Using Async await
async function SetItem(){
try {
await AsyncStorage.setItem(prod_id, '1')
alert('Added to Cart');
} catch (error) {
console.log(error);
}
}
with then and catch
function SetItem(){
return AsyncStorage.setItem(prod_id, '1')
.then(()=>{
alert('Added to Cart');
}).catch((error)=> {
console.log(error)
})
}
calling this method
this.SetItem().then(()=>{
console.log("value is set");
})
I'm trying to add error catching to the render function of a component. This works fine when I throw an error in the actual render function, but if there are errors in the children of the component, the try does not catch the errors (or they are intercepted by the child component error handlers, I'm not sure?)
Is there anyway to force the errors to the parent.
const SimpleComponent = React.createClass({
render: function(){
try{
throw 'new error'
return <div>{this.props.children}</div>
}catch(e){
console.log('error', e);
}
}
})
The above works
const SimpleComponent = React.createClass({
render: function(){
try{
return <div>{this.props.children}</div>
}catch(e){
console.log('error', e);
}
}
})
const ChildComponent = React.createClass({
render: function(){
throw 'child error'
}
})
<SimpleComponent>
<ChildComponent />
</SimpleComponent>
This above does not catch
Use componentDidCatch() method from react 16.
Check this for more info
You can leverage React's BatchingStrategy API to easily wrap a try/catch around all of your React code. The benefit of this over window.onerror is that you get a nice stack trace in all browsers. Even modern browsers like Microsoft Edge and Safari don't provide stack traces to window.onerror.
Note that this solution won't always prevent React from getting into a bad state. However, this solution will at least allow you to handle the error, for example displaying an error banner/modal, or sending stack trace error logs to your service.
Here's what it looks like with React 15.4:
import ReactUpdates from "react-dom/lib/ReactUpdates";
import ReactDefaultBatchingStrategy from "react-dom/lib/ReactDefaultBatchingStrategy";
let isHandlingError = false;
const ReactTryCatchBatchingStrategy = {
// this is part of the BatchingStrategy API. simply pass along
// what the default batching strategy would do.
get isBatchingUpdates () { return ReactDefaultBatchingStrategy.isBatchingUpdates; },
batchedUpdates (...args) {
try {
ReactDefaultBatchingStrategy.batchedUpdates(...args);
} catch (e) {
if (isHandlingError) {
// our error handling code threw an error. just throw now
throw e;
}
isHandlingError = true;
try {
// replace this with whatever error handling logic you like.
// e.g. dispatch redux action notifying the app that an error occurred:
// `store.dispatch({type: "EXCEPTION", payload: e});`
console.error(e);
} finally {
isHandlingError = false;
}
}
},
};
ReactUpdates.injection.injectBatchingStrategy(ReactTryCatchBatchingStrategy);
Full writeup here: https://engineering.classdojo.com/blog/2016/12/10/catching-react-errors/
I'd recommend the (currently) unstable lifecycle event unstable_handleError in your parent component.
public unstable_handleError(err: any) {
this.setState({
error: err
});
}
The error hook will likely become official API in future releases.
See this issue for details
https://github.com/facebook/react/issues/2461