I have a react typescript component that has the following componentDidMount method:
componentDidMount() {
ComponentFields.get(this.ComponentName)
.then(activeFields => {
this.setState({ activeFields });
});
}
It has a state interface with following field
export interface ISettingsPageState {
activeFields: Dictionary<IComponentField>,
}
where IComponentField is an interface.ComponentFields.get(componentName: string) is a static method which returns a Promise<IDictionary<IComponentField>>.
It works fine the first time it loads but when I refresh the page, the setState method in componentDidMount throws the following exception:
Uncaught DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
Anyone have any idea what could be causing this?
It turns out that it was a child component throwing the error. Even though the exception was being thrown at the setState line, the problem was in my rendermethod. If anyone has the same problem, I would suggest taking a look at the render method to see what's going wrong.
Related
useEffect(() => {
let val = window.ethereum.isConnected();
if(val)
{
console.log("here");
getAddress();
toggleConnect(val);
updateButton();
}
window.ethereum.on('accountsChanged', function(accounts){
window.location.replace(location.pathname)
})
});
React Hook useEffect contains a call to 'toggleConnect'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass [location.pathname] as a second argument to the useEffect Hook.
Please, could anyone help with fixing this error?
I tried fixing it by using // eslint-disable-next-line. The warning went away but I am facing issues deploying the website online. It is giving error messages.
I am not very clear about the process to be able to handle errors globally in a react-native application. How to capture any aplication error and response according to it?, for example show an error screen and a button to 'go home', or run a especific code like retry a request so the user can recover from such an error. which approaches are used in order to handle errors globaly in react-native?
The error boundaries API only works with class Component, and a class component becomes an error boundary if you define one of these lifecycle methods static getDerivedStateFromError() or componentDidCatch().
React-error-boundary is a simple reusable component based on React error boundary API that provides a wrapper around your components and automatically catch-all error from the children’s components hierarchy, and also provides a great way to recover your component tree.
My suggestion is to wrap every navigation screen in your Application with a react-error-boundary component and provide a fallback component to Make sure the user knows what’s happening, and maybe you can recover the screen with a rerender.
The best way to do it is to create an Errorhandler component like the following.
import * as React from "react";
import { ErrorBoundary } from "react-error-boundary";
import { View, StyleSheet, Button } from "react-native";
import { Text } from "components";
const myErrorHandler = (error: Error) => {
// Do something with the error
// E.g. reporting errorr using sentry ( see part 3)
};
function ErrorFallback({ resetErrorBoundary }) {
return (
<View style={[styles.container]}>
<View>
<Text> Something went wrong: </Text>
<Button title="try Again" onPress={resetErrorBoundary} />
</View>
</View>
);
}
export const ErrorHandler = ({ children }: { children: React.ReactNode }) => (
<ErrorBoundary FallbackComponent={ErrorFallback} onError={myErrorHandler}>
{children}
</ErrorBoundary>
);
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
alignItems: "stretch",
justifyContent: "center",
alignContent: "center",
paddingHorizontal: 12,
},
});
As you can see I am using an error fallback component to provide more information to the user instead of a white screen.
I also added a try again button to programmatically re-render the screen as a way to recover it and solve the issue. when the user clicks the try again button the error boundary will trigger a rerender for the Screen Component which can help to avoid error and show the correct components.
Read More about Error Recovery
To mention, I am also wrapping the error boundary component for every component that may throw an error.
Is Error Boundary enough for JS Exceptions?
Unfortunately, it’s not, Error boundaries do not catch errors for :
Event handlers
Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
Errors thrown in the error boundary itself (rather than its children)
(Source: Docs)
These limitations lead us to use a react-native-exception-handler to create a global handler for the App that can catch all uncaught Js errors.
react-native-exception-handler is a react native module that lets you register a global error handler that captures fatal/non-fatal uncaught exceptions.
To make it work you need to install and link the module then you register your global handler for Js exception like the following :
import { setJSExceptionHandler } from "react-native-exception-handler";
setJSExceptionHandler((error, isFatal) => {
// This is your custom global error handler
// You do stuff like show an error dialog
// or hit google analytics to track crashes
// or hit a custom api to inform the dev team.
});
Native Exception
As I already mention Native Exceptions were produced from Native modules errors and Internal native react native code.
From my experience, we usually face few uncaught Native exceptions compared to Js ones, the good news is that we are going to use the same library( react-native-exception-handler) to handle native exceptions too but you cannot show a JS alert box or do any UI stuff via JS code. The only solution was to show a native alert provided by the library but native code has to be written in case you want to customize the alert.
To create a global handler for Native exception, you only need to register your handler using setNativeExceptionHandler function like the following :
import { setNativeExceptionHandler } from "react-native-exception-handler";
const exceptionhandler = (exceptionString) => {
// your exception handler code here
};
setNativeExceptionHandler(
exceptionhandler,
forceAppQuit,
executeDefaultHandler
);
Tracking Exceptions
Handling exceptions without tracking them has no sense because all the solutions we discussed only improve the user experience and give more information to the user about the error instead of a white screen or an app crash.
Sentry is a cloud-based error monitoring platform that helps us track all these errors in real-time. By creating a free account and installing react-native-sentry you can use it inside your handler (js and Native) to send the stack errors using captureException like the following:
// ErrorHandler.js
import * as Sentry from "#sentry/react-native";
const myErrorHandler = (error: Error) => {
Sentry.captureException(error);
};
Now, Make sure to fix your errors.
Whenever I hot reload my app or an unhandled exception gets thrown and crashes my React Native App, this error message pops up. My index.js has
firebase.messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log(JSON.stringify(remoteMessage));
});
There could be a few reasons for that. It might be possible that JSON.stringify(remoteMessage) is getting crashed and since you have not added catch in your promise chain you are getting the unhandled exception.
Could you modify your code to below:
firebase.messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log(JSON.stringify(remoteMessage));
}).catch(e => {console.log(e)});
And then analyze the crash stack
The re-base documentation is quite clear on the matter when it comes to syncing one property of your react app's state with firebase: https://github.com/tylermcginnis/re-base#syncstateendpoint-options
It says to use syncState in the componentDidMount method of your component like this:
componentDidMount(){
base.syncState(`shoppingList`, {
context: this,
state: 'items',
asArray: true
});
}
I want to sync two different properties, so 'shoppingList; and 'weeklyBudget'. I tried to duplicate the statement like this:
componentDidMount(){
base.syncState(`shoppingList`, {
context: this,
state: 'items'
});
base.syncState(`weeklyBudget`, {
context: this,
state: 'budget'
});
}
But the console just throws the following error:
Uncaught Error: Objects are not valid as a React child (found: object with keys {}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of Order.
How do I could sync multiple properties on state between React app and Firebase database using re-base?
If you add asArray: true to the object right after context: this, you should be fine.
It works like this for me. I am not satisfied with this code at all myself because I have seven blocks that connect to different endpoints. An alternative might be to use fetch and resolve via Promise.all([x, y, z]).then()
I have a strange issue and I'm not sure what part of my stack is responsible for throwing the error. I currently have an es6/webpack/react-router rc2/flux(altjs) isomorphically(universally) rendered application. If there are any bugs on any part of the frontend(syntax error or otherwise) or an api endpoint is incorrect/not responding the appropriate data format(i.e. an array isn't being sent back which therefore cannot be mapped over by one of my react components) the server crashes with the following error
Cannot read property statuscode.toString() of undefined
Is this react-router related? Webpack related? React related? I wish I could have a more informative stack trace because as I work through the backend as I'm not sure what is incorrect, whether it is front-end code or backend code. Is there any way to "catch" what is occurring. To clarify nothing else changes but the expected data structure which throws this error.
Edit:
export default class Dashboard extends React.Component {
constructor(props) {
super(props);
this.state = {
data: DataStore.getState().data
};
}
render() {
return (
<div className='dashboard'>
<Tile gridWidth='cute-6-laptop' linkTo='/data/temperature/water' size='regularTile' title='Water Temperature'>
<OverviewChart data={this.state.data.Water_Demand.devices} mapObj={mapObjs.water} keyData={[{key: null, value: this.state.data.Water_Demand.devices[2].readings[this.state.data.Water_Demand.devices[2].readings.length - 1].rate, units: this.state.data.Water_Demand.devices[2].rateUnits}]} chartClass='interiorTemperature' includeNavChart={false} includeBarChart={false} w='473' h='180'/>
</Tile>
</div>
);
}
}