-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Debugging React Native #69
Comments
Systrace - Issue #15003 Systrace is one useful tool which has been broken in the open source release for 1.5 years now with no available fix or workaround. Initially it was due to the change away from The actual issue is that Facebook's fork of React Native has a private library which allows Systrace to work. @gaearon originally posted that it would be looked at in December 2017 or January 2018. In August 2018 @axemclion confirmed that this was not an issue for the internal Facebook version. The proposed solution was for the community to submit a PR on top of an unspecified "very old" PR. It's a tool that you don't need to use too often, but that fact that it is included in the development menu but has been completely broken for 1.5 years is not a good situation to be in. As @jamesreggio stated, the community ideally should have stepped up to fix this, however, it would likely take a non-trivial amount of time and could conflict with Facebook's internal tool which would lead to any PR opened to fix the issue being a real slog to get merged (even more than usual). For me, the obvious solution is for Facebook to submit their implemrntation to the open source project, however, it's not clear if that is allowed to happen. |
Hi, For me the issue I get the most is "unactionnable stacktraces" Usually when having a stacktrace, we can click a stack item and be lead to the original place of the exception. But very often, the stacktrace of uncaught exceptions, or exceptions received in error boundaries are totally unhelpful. It looks to me at some point the stacktrace is lost. If I put a try/catch in render, I'll get the correct stacktrace, but if the exception propagates to upper levels it is lost. I'd like that an exception thrown in render, and logged in componentDidCatch, to have the same stacktrace as the if I put a try/catch in render myself. ie: clicking on the first stacktrace item would lead to the root cause. |
I sometimes get crashes when opening the app that don't result in red screens. These can be caused by configuration of native code, and I end up having to open logcat for Android or Xcode to read what the native-level logs are telling me. Since that info already exists, it'd be nice to have an easier way to access it than by actually opening logcat or Xcode. |
Separately, regarding stack traces, it seems that I don't reliably get line numbers, or at least the line numbers are unhelpful. Sometimes I just get a reference to the bundle file. As in @slorber 's screen shot, Along with that, |
Debugging network requests feels kludgy. There are lots of different solutions, but nothing standardized. |
Hot reloading is awesome, but is not working as good as it could (actually it is even crashing for me on iOS if I am not debugging). Dan Abramov had a real good blog post about what would make hot reloading great (also makes a point that rn implementation is not complete): https://overreacted.io/my-wishlist-for-hot-reloading/ |
When debugging the app in iOS, the number of times that I get a red error screen telling me that the package server is not ready for debugging, when it absolutely is, is very frustrating, especially if it happens during the testing of a sequence of events and reloading the view takes me back to the beginning of the sequence. Often my only option is to restart the application and hope that it works better next time. |
To second that, often it will remain on "not ready for debugging" directly after telling it to debug JS remotely - I'm guessing because the server is in the process of launching. You have to refresh again for it to actually connect. |
This issue seems to persist in the wild; facebook/react-native#12830 It is related to AsyncStorage blocking (not resolving) during debug sessions on iOS/Android device/emulator/simulator and variants. I personally have not experienced it recently. |
An ongoing bug which I'm getting really highlights how inadequate React Native's tooling is when it comes to figuring out where a native crash originates in your JS code. Let me outline the issue and point out the debugging pain points. The Android crash report shows the following: Fatal Exception: com.facebook.react.bridge.JSApplicationIllegalArgumentException: Error while updating property 'transform' of a view managed by: RCTView
Caused by java.lang.reflect.InvocationTargetException java.lang.reflect.Method.invoke
Caused by com.facebook.react.bridge.NoSuchKeyException: translateX
For iOS, in release mode, it doesn't actually crash the app. But for some reason, the interface freezes up and doesn't respond well, or unexpected things happen when you tap buttons. However, I can sometimes replicate the crash locally, and the Xcode log says:
The redscreen crash that shows up in the simulator indicates that So far in the debugging experience, I know that a crash happens, and that it's caused because at some point After further investigation, I found that it typically happens after a particular action happens. So now I can reproduce it in a simulator fairly regularly (though still not 100% reliably). At this point, I need to figure out where
My next thought with debugging was to set a breakpoint in Xcode whenever any exception happens, so I can see much more detailed information about the crash. This worked really well, I was able to examine the call stack and local variables for the entire crash. However, the call stack was entirely internal react-native code. Since the transform values are obviously sent over the JS bridge, after it gets into the native code, everything is handled by fairly generic code which runs on every Natively debugging the crash only showed me the local variables for native code - but it was impossible to figure out which of this code ties back to my JS code. I need to know which component it originates from in order to fix it or to file a bug report. The most I could find out after some digging through the stack trace was the While setting a breakpoint in the native code, I pulled out the data structure which contains the null value. It looks like this: I'm not sure why null was never validated before it got to the point in native code where it tried to apply the transform logic to the values. Seems like it should have been. Doing a bit more thought, my next hunch is based on the fact that the action sets particular redux state that re-renders a component. And that component would not be visible when the redux state updates. Thinking about the components that would update, I narrowed my search for const progressStyle = {
backgroundColor: color,
height,
transform: [
{
translateX: this.state.animationValue.interpolate({
inputRange: [0, 1],
outputRange: [innerWidth * -INDETERMINATE_WIDTH_FACTOR, innerWidth],
}),
},
{
translateX: this.state.progress.interpolate({
inputRange: [0, 1],
outputRange: [innerWidth / -2, 0],
}),
},
{
// Interpolation a temp workaround for https://github.com/facebook/react-native/issues/6278
scaleX: this.state.progress.interpolate({
inputRange: [0, 1],
outputRange: [0.0001, 1],
}),
},
],
}; This array is set up with the same order and same properties that the object which causes the issue has been. That's really encouraging. But now I need to figure out why any of those values would ever be set to null. So I set So at this point I've been investigating this crash for more than 20 hours, and the existing similar issues and Stack Overflow posts are rare and unhelpful. I've outlined this debugging experience so that you have some more material examples of how difficult it can be to debug React Native issues. Here are my big takeaways:
Basically, I think my conclusion is that there has to be some easy way to debug through the JS bridge such that internal React Native functions that actually do the bridge work are hidden. For example, I would rarely want to have any information about the internal functions which actually implement the bridge on both the JS and Native sides. But as is, the majority of debug information is just printing out the internal bridge implementation and view updating code. What we need to know is what JS file this error originated from, and how it propagated through our own code, or through a 3rd party library's code, in order to end up in a bad state. It definitely seems like a really tough problem to solve, so I hope this post has been helpful, though it is quite long. Happy Holidays! :) P.S. If you have any suggestions for actually fixing this dang crash, please let me know! |
@noahtallen thank you so much for that level of detail. It is amazingly helpful and really shows the scope of the problem, especially when dealing with 3rd party code. This is definitely something we will need to talk about as a group. |
@matt-oakes Have you tried the Javascript Profiler in the standalone React Native Debugger? You can select the debug worker thread to make flame charts of JS calls. I use it a lot to find out why the JS thread is not keeping up. I find that using the javascript profiler, combined with Android systrace and various iOS Instruments, is a decent workaround to get insight in what is slowing down any app. I agree Systrace should be fixed of course. |
When you make a change to a file in your bundle and restart your app (either from Xcode or via the "Reload JS" button), breakpoints in Chrome devtools are not respected. This might be because it takes time for Chrome devtools to process the source map. It would be great if the RN team looked into it! |
Hey everyone! Thanks so much for participating in this discussion so far. I think we have a good understanding of things that are broken. I'm interested in fixing a ton of the smaller annoyances, like unhelpful error messages. A lot of you have been sharing error messages but no clear repros. Would you mind sending me your best code examples that I can just drop into my |
Here's one: Unhandled Promise Rejections have unhelpful stack traces, @cpojer. We deal with this a lot. import React, {Component} from 'react';
import {Text, View} from 'react-native';
export default class App extends Component {
componentDidMount() {
async function crash() {
throw new Error('crashed')
}
crash()
}
render() {
return <View><Text>Jamon</Text></View>;
}
} |
My app got this issue on Sentry |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@namvoeh Cause is empty string ( // Invariant Violation Error
const Foo = () => (
<View>
{ '' && <Bar /> } // if value is empty string
{ 0 && <Bar /> } // if value is zero
</View>
)
const Foo = () => (
<View>
{ value ? <Bar /> : null } // 1. use ternary operator
{ !!value && <Bar /> } // 2. use !! expression to make it boolean value
</View>
) I hope this will help you 😃 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Thanks for participating in the discussion. Please do not discuss how to solve specific problems here as it's not a support forum. I'm looking for concrete code examples that lead to bad errors or crashes. Screenshots of issues without repro steps are unfortunately not really actionable. |
This comment has been minimized.
This comment has been minimized.
When we write something like: let console = require("console"); result:
|
@adamczyk777 You're making sth similar in reanimated. Maybe you want to push it here as well? |
Any solution to this problem ? |
As @osdnk mentioned before I was trying to resolve some issues with poor error messages in ReadableMap and other types that are used when passing stuff through the bridge. Here's a link to PR I opened a while ago Link. So what's the issue right here?Let's focus on Android first, because that was the case that started the discussion about it in reanimated. When we pass objects that describe animated nodes, the JS object after being passed through bridge gets translated to What would be cool to have in the future?Default error messages could be better by default, not only huge "what". Also if getString was overloaded and there was a possibility to pass an error message if a problem occurs when reading a value that would also be great. That's for Android, the problem on iOS also exists, because values get cast to different values, in ReadableMap there is no warranty of types or sth like this. In the end, I also wrote error messages through objC macro when the value is wrong I print the same error messages as in Java. Hope my comment makes sense, if not reply I can clarify 😃 |
Sometimes it becomes pain to debug the app because you are not sure where to look at. If you are experienced developer, you can spot the problem but this is just a frustration to a newcomer Problem 1The most difficult bug to debug is when you left a text accidentally outside of a text component. Eg. <View>
<Text>Hello World</Text>>
<View> ^
And its error message doesn't help much. You have to manually search to component to find if there is any extra character. My suggestion is
<View>
<Text>Hello World</Text><Text>></Text>
<View>
Problem 2Another similar error message is when you provide class MyComp extends Component {
state = {
uri: null
}
render(){
<View><Image source={{uri: this.state.uri}} /> </View>
}
}
My suggestion is
|
RN is like black magic, sometimes it works and other it doesn't, it's like that, deal with it :D |
None of the debugging tools listed in the documentation work as stated in the docs anymore. Some kinda work, some are totally broken, but there are really no working options left for debugging UI performance, at least on Android. Systrace is broken, it is missing the information the docs state it should show. Chrome debugger no longer records user timings or any information in the performance tab. It only records the debugger webpage now. This means chrome debugger is limited to viewing console logs and taking basic CPU profiles. The most useful tools no longer work. react-devtools are broken, they lose connection to the app constantly making profiling impossible. They also commonly reduce performance to the point the app is unusable making the tools useless for debugging especially perf related things. Needless to say this is extremely frustrating. Users complain about poor performance on Android but we have no tools to diagnose and fix the issues! |
How to debug js thread block in production? |
I'm also looking for solution, I've been following this issue for a few months but still no working solutions in the latest updates. |
I'm surprised it wasn't mentioned yet (maybe it's off topic?) but I'd really like a way to trace/detect component updates. I recently authored a not so well written component that would re-render indefinitely but wouldn't crash the app so it was hard to notice. I know this was removed and readded for DOM only. It'd be awesome if we had RN support too. |
Debugging in general is an awful, even unusable at times, experience on the Android Studio emulator. It slows the app down (especially animations) to the point where the debugger is sometimes unusable. I've tried all the tricks removing console logs, different android versions in emulator, checking time matches, checking haxm acceleration, different emulator configurations, using hermes. None of it helps. I'm on a very fast modern desktop machine so it's not my machine perf. There are a few symptoms:
Perhaps the worst part about this is that there's no way to diagnose the issues. Per my previous post in this thread most of the Android perf tools are broken. Sometimes the chrome timeline works but it shows no issues with my app code, whatever is killing perf is inside RN out of reach of the JS thread. This all leads to a supremely frustrating experience. There are only two ways to debug my app -- via console.log spam or via buying a mac where iOS simulator perf is flawless and stable. |
@AndrewMorsillo I don't think buying a mac will fix anything. I'm on a 2018 MBP and Android emulator performance is the same as what you describe I was recently building an accordion component using I tried using |
@gwmccull When I said "buy a mac" I meant to use the iOS simulator. The iOS simulator has a perfectly smooth experience debugging react-native. The Android debugging situation is terrible on any platform. It's especially problematic for my use case because we have animations running nearly constantly in the app. Turn on Android debugging and a tap can take 2-6 seconds to register which isn't really usable for debugging. |
For Android debugging I've generally given up on the emulator due to the slowness and use a real device via Vysor instead: https://vysor.io/ It's been working reasonably well so far... Using Vysor rather than just the device directly means I have it on my desktop to tab to, like the emulator and I can use R R to refresh, etc rather than having to shake the physical device |
For Android, I think the cause of this are some options of the used AVD. There are quite few responsible for performance when you creating an AVD. on my MBP 15 2018 AVD works like a lot better than the iOS simulators (even iPhone SE not that smooth). But I cannot point where those changes should be made. But the downside of it is usage of 100% of the thread all the time. |
Hey folks, so this has been for almost 2 years. Any improvement or action item resolves around this? I am still.having a bad experience debugging react. |
Well I can debug Unix software and drivers, I can debug remote microcontroller running firmware over JTAG/SWD, but I could not get into debugging my React Native application running on the real phone over USB. I just get some website but where is the debugger so I can trace my application? Where are instructions and examples? The documentation is laconic and not really hlepful for noobs in JS/RN ;-) |
@cederom that website is the debugging tool. You can open the Chrome console and see any console statements logged out there. The metro bundler (in the terminal) will also show console statements. The Chrome console also allows you to switch to the source and do real-time debugging with breakpoints, step through lines of code, etc. However, the debugger can be a little difficult to use because it's easy to fall out of a component function and end up in a function from React or another library I generally just use console.log statements for 99% of my debugging |
Hello @gwmccull :-) Thanks for the hints :-) What you mention seems Logging not Debugging. I have done that already by hand inside my code to know that is going on, what is the progress, what is the data, etc. But this is just a log that I need to create myself by hand. I have it directly on my I am using From a Debugger I would expect to see the code flow, threads, memory map, variable state and values, alter GUI state along with other components, set breakpoints and watchpoints, etc etc etc. When entering that "debug website" I can not even see source code of my application under development, just the website itself. Maybe I am doing something wrong? Is this Debugger just a tricky name or there is a real Debugger behind it (lets say like GDB)? What are the features of available Debugger (I have found no list) and what more it gives me than |
What about errors with Working code in react-native 0.64.2, I tried upgrading to react-native 0.65.1 then I got that error but it looks like a dead-end for me because I can't find any lead other than the upgrade so it must be something in react-native 0.65 or maybe one of my dependencies? I don't know, don't even know where to look... I've stuck in this problem for 16 days now and can't upgrade because of it. |
@cederom I don't use any logging libraries so I can't recommend anything there I haven't really used Expo but according to their docs, you can use the Chrome debugger. It's a full debugger with the ability to see variables and step through code. This blog also provides some additional info about interacting with the Chrome debugger. Although, one thing that I didn't see mentioned that I believe you can use is to enable "pause on caught exceptions" and then use a @aprilmintacpineda I don't know what causes that error. If it were me, I would try basically commenting out the entire app (including all of the imports) except for a single |
Hi Everyone, If anyone knows a solution for the below issue. Please let me know. Because most of the crashes in our playconsole are related to this bug only. But we could not know what it is. Everyone is talking about arm based cpu architectures. So please explain in detail if you guys know. Bug: SIGSEGV · Segmentation violation (invalid memory reference) /data/data/in.onecode.app/lib-0/libjsc.so:1013576 0x74949b1748 /data/data/in.onecode.app/lib-0/libjsc.so:1327084 0x74949fdfec /data/data/in.onecode.app/lib-0/libjsc.so:1241260 0x74949e90ac /data/data/in.onecode.app/lib-0/libjsc.so:1283208 0x74949f3488 |
Update to the promise rejection debugging experience with React Native 0.66.4: Prettier, but still doesn't give useful debugging info as to what was thrown and where it occurred. This is still something that affects us daily, so I'd love to see improvement to this experience. Ref: #69 (comment) Note that using function component syntax doesn't change the result, if anyone was wondering: import React, {useEffect} from 'react';
import {Text, View} from 'react-native';
export default function App() {
useEffect(() => {
async function crash() {
throw new Error('crashed');
}
crash();
});
return (
<View>
<Text>Jamon</Text>
</View>
);
} |
Lately I am receiving completely unactionable stack traces around promises. It has never been as bad as it is now. No line number, no calling function, nothing. Just lots and lots of |
How's the symbol publication for Hermes going? I know not a large number of people would be affected by this, but for those who are affected, it's a night and day difference. Opening a tracking issue would be nice but I didn't open one since I wasn't quite sure which repository I should be posting. |
This issue is part of What do you dislike about React Native?.
The second most voted answer was that debugging React Native is painful, see #64 (comment).
The problem statement is very broad ("Debugging is hard") and we would like to gather more context about the actual issues that people are experiencing. Please use this issue to list every piece of content you can related to debugging React Native: your own stories, links to issues, blog posts, complaints or any other rants you can find. Thank you!
The text was updated successfully, but these errors were encountered: