-
Notifications
You must be signed in to change notification settings - Fork 47.2k
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
Community feedback on console silencing #21783
Comments
I was confused myself and asked this question. Despite it was only 3 days ago, the question got 27 upvotes. |
The old behaviour was confusing to anyone new to React, until they learned about it. The new behaviour is now confusing even to veteran users of React, even if they knew about In my opinion, it's now a trap anyone could fall into. |
The problem with the old behavior wasn't just that it was confusing — it was that it's actively interfering with product code debugging. The duplication was creating a lot of noise. The problem with the new behavior is that it's also interfering with debugging — but specifically for double rendering issues. If you're not debugging specifically double rendering issues, I wouldn't say it's confusing. But when you are, it's confusing in a much deeper way. So from my perspective it's a tradeoff between a medium level annoyance in a common scenario (old way) against a very high level annoyance in a relatively less common scenario (new way). Obviously both of them are annoying and I totally understand the perspective that the tradeoff is not worth it. (There's no real need to explain why in each follow-up comment — I think we all understand what the confusing parts are.) Personally, I don't think either of the tradeoffs are great options. I wonder if there's something in the middle that would be better. At least having a way to opt in/out of the silencing seems like it would be very useful. Regardless of the default. So this seems like a clear first step. Maybe if this is integrated into DevTools, the default could be changed but with a message printed before any double logs warning you why they happen (and suggesting you to pick a preference in DevTools). And then if you pick a preference in either direction, it doesn't bug you again. (I'm just throwing things out there — not sure this makes sense!) |
Frankly, everytime developers thinks that they can improve something by changing the behavior of a system method, then they should return to school. |
Let's keep this conversation polite; there is no need to tell people to "go back to school" and so on. Your point is well-understood without that.
That to me speaks in favor of silencing because unless you're debugging double-rendering issues specifically, seeing the logs without duplication is more convenient. It's only when you're debugging double-rendering issues that this distinction starts mattering. (But I fully agree that it can be deeply confusing in that scenario.) |
@gaearon Thanks for explaining your perspective. I don't think my opinion has changed but this helps me understand a different way to see the trade-off. I wonder if the scale/structure of FB product eng makes the common case more common than it is elsewhere? Anecdotally, folks at my company put console logs in render to understand render cycles about as often as they do to inspect values, so in that world it feels more like a minor vs. high level of annoyance in equally common scenarios.
I agree that a toggle would be very helpful. At a glance, the PR I noted (#19710) seems like a complete implementation, and appears to have new code pushed since you and @bvaughn last reviewed it. Do you recall if this is a question of time/prioritization, or if there were concerns with the approach? I can offer some help if it's something like the latter and the original author isn't available.
This makes a lot of sense to me. Perhaps DevTools could also print a message on init if strict mode is enabled in any part of the app and a preference hasn't yet been chosen? Something along the lines of: "Strict mode is on; click here to read more about what this means; click here to set a preference for how to handle logging." So that it's less of a surprise when it happens later.
I think that @ondrejhanslik meant "underestimating". @ondrejhanslik, I agree with some of your sentiment but consider that this kind of language can make it less likely that this will be changed. React is made by humans for humans and kindness goes a long way. 🙂 |
Unfortunately, the PR you linked to wouldn't implement the functionality you're describing. The shared patching methods it override in the DevTools build are compiled into the react-dom bundle (separate copy, like everything else in Implementing this functionality would require adding an additional interface between react-dom (and other renderers) and React DevTools |
@bvaughn Thanks for the context. If you have the time to dive in: My understanding of the PR implementation was that toggling the setting in DevTools would set a global variable on the app page, which would then be read by react-dom (or other renderer) while deciding whether to patch the console on a given render. So I don't immediately see why the separate copy is a problem, or why an interface is necessary. Is the issue that the
Assuming this is necessary, do you think it would be a reasonable self-guided task for an external contributor, or do you think it requires a core member's time? I saw the contributing guide you posted recently. Happy to take a look if you think it's within reach. |
Can you clarify a bit more what you mean about understanding render cycles? Since double rendering is "shallow" (it happens at each leaf call), it seems like it is easier to understand the actual render cycle with silencing. Since then the noise is reduced and you see the actual order in which React walks the components.
That is also how I interpreted it! I'm probably missing something @bvaughn is seeing but I'd appreciate a clarification here too because I thought something like this should work. |
@billyjanitsch @gaearon My bad for not taking more time when writing my response. The PR would work kind of but not in the way I think it should. You're right that the code in const {__REACT_DEVTOOLS_SUPPRESS_DOUBLE_LOGGING__: suppressLog} = canUseDOM
? window
: global; That means your setting wouldn't take place unless you changed it in DevTools and then reloaded the page. I think this is confusing because similar settings (e.g. component filters, inline errors/warnings) apply immediately. I also don't think we should couple global DevTools variables with code in
I hope this answer is clearer. Sorry for my rushed response earlier.
Assuming it's something the team agrees to accept/land, I think it could be a self-guided task, following the precedent of the PRs I mentioned above and the new contributing guide. I'm not sure how I feel about this change. @gaearon: Let's bring it up during the next core sync and see how others feel? If there's consensus that it's okay, I'll shepherd it through. |
For what it's worth, people commented on the SO question with the following suggestions:
Sorry if this was already discussed/considered! 😅 |
React double-renders components as it goes along. (It doesn't re-traverse the whole tree.) Such a message would be printed a lot of times (which would be really noisy). |
Good point! Maybe prefixing/suffixing duplicate renders logs would reduce the noise, coupled with an option to opt-out of logging (silencing), as discussed above, would help minimize any surprise and/or confusion? Though I'm not of fan of hijacking the console. If the option is ever added, I feel it would be great to have it mentioned in the console log for discoverability when strict mode is used in dev. Even a log informing the user of strict mode being used would greatly help as I've seen/closed a lot of questions on Stack Overflow about the initial duplicate logs with strict mode in the past (mostly the reason I'm commenting here). |
I think I understand the reason for this request, but I'm really wary of console warnings like this. Noisy consoles make developers pretty angry, and unfortunately we can't just show it once and save a cookie– because people don't keep the console open until they need it (so such a one-time-only warning would be missed in most cases). I do understand the frustration here. It sucks to lose time investigating something weird only to find out that a framework or tool has done something clever and unexpected. I like the idea of using DevTools to improve experiences like this, but I'm not sure how we teach people to look to DevTools for this sort of thing. Hopefully our new docs (which will have a dedicated DevTools section) can help with this. |
My proposal here would be that we show a message until you explicitly pick a preference in DevTools. So you can "shut up" the message by making a choice in the settings. So it's a bit noisy but it shows once per session and you can make it disappear forever by installing DevTools and choosing a preference (in either direction). |
I'm concerned that this feels heavy handed. We're essentially forcing people to install a browser extension (that may have performance implications) and to leave it enabled to opt out of otherwise annoying console spam. I love DevTools and I'd love to see more people install it and use it, but I'm concerned about this approach. |
That's already the case though. We show a console message at the start every time if you don't have DevTools installed. So it's not that different from what we already do. |
Oooh. Actually this got broken due to Fast Refresh. Fast Refresh integrations are being detected as DevTools hook so we're not actually showing that log anymore. |
I forgot we did that 😂 I guess we could expand that message then? (I don't think we should log something every time we double render, regardless.) |
Yeah. Maybe the message could be different depending on:
And then there is no message if you have extension, and either are not in StrictMode, or you are in StrictMode but have picked a preference in DevTools. |
Something like that seems reasonable, yeah. |
@bvaughn I noticed this too and agree that it's undesirable, but it seemed simple to fix (by reading the variable in
...that totally makes sense. Thanks for linking those implementation examples. 🙂
Let me know how the sync goes. Happy to help if you're willing to accept the change but don't have time to work on it.
@gaearon I like this approach a lot. Thank you both for your time spent considering. |
Just to toss in a couple more cents: Agreed that this is a constant source of confusion, especially at the beginner/learner level. I think that the suggestions for altering behavior and the messages based on setup and DevTools config options sounds like an excellent idea and a very good candidate for improving this situation. And I really appreciate the quality discussion in this thread from both sides! Good issue writeup, great explanation of tradeoffs, some brainstorming, offers of assistance, and some forming consensus. That's some nice OSS collaboration in action :) |
TIL about this, and I agree it's really confusing (both before and after the silencing). The silencing here makes it really difficult to debug double-rendering issues and causes confusion when I'm trying to explain that constructors/renders run twice in StrictMode. I think I agree that a console message that at least tells you that react has silenced a double-rendered console.log even one time would be ideal here. We'd only need to print the message if a console.log is silenced. Otherwise we don't need to console.log it at all.
And this is why I think we should only print it once and only if a console.log() is actually silenced. For example, right now react sets this like:
What if instead, it set it like...
This would be similar to how we console.log non-fatal errors in production code at FB: |
Yeah, we'd only print such a message once (per session) if we added it. (Similar to how we only print other DEV messages once to avoid clogging the console.) My comment above was more meant to point out that we really wouldn't want to print a message before every time we silenced the console. I think we could go further still than the code example shown above, and only print the message if a component actually tried to log a message to the silenced console, e.g. diff --git a/packages/shared/ConsolePatchingDev.js b/packages/shared/ConsolePatchingDev.js
index ed7f7f7d18..4c5618f3eb 100644
--- a/packages/shared/ConsolePatchingDev.js
+++ b/packages/shared/ConsolePatchingDev.js
@@ -21,7 +21,16 @@ let prevGroup;
let prevGroupCollapsed;
let prevGroupEnd;
-function disabledLog() {}
+let hasWarnedAboutDisabledConsoleLog = false;
+function disabledLog() {
+ if (!hasWarnedAboutDisabledConsoleLog) {
+ hasWarnedAboutDisabledConsoleLog = true;
+
+ // Print the double-render silenced console notice here.
+ // This way if no double-rendered components use the console,
+ // we won't print the message unnecessarily.
+ }
+}
disabledLog.__reactDisabledLog = true;
export function disableLogs(): void { |
That is exactly what I just suggested @bvaughn... 😄 |
I misread your suggestion as (always) printing the notice the first time before we started double render. My bad. |
Hi, I know this issue has been discussed endlessly so I apologize for bringing it up again. I hope this issue is net helpful. 🤞
Quick summary: as of #18547, React 17 silences console logs during the second rendering pass in strict mode, in dev. It's a trade-off between the confusion of logging multiple times for a single render pass and the confusion of only logging once even though the code was actually called twice.
Note that there's an outstanding PR to make it configurable (#19710) but it seems to be stalled awaiting review.
Since the change was released, I've seen a number of issues in which folks have been confused by the behavior, e.g.:
The response from the core team has generally been that, yes, this behavior can be confusing, but the previous behavior was equally if not more confusing. It's a trade-off without a clear answer. (Examples: 1, 2, 3.)
I totally understand this perspective and I've tried to internalize it, but, frankly, the longer it's been since the release, the more it seems to me like the new behavior is actually just significantly more confusing for most people. My signal is:
Altogether, the change was clearly well-reasoned and well-intentioned, but now that it's had some time to settle, what I'm asking is:
I hope this is a fair take and a helpful set of questions to ask. Thanks for taking the time to read.
(FWIW, if I had to guess, I'd propose that one reason for the new behavior being more confusing is that the old behavior is only confusing until you learn that strict mode = double render, whereas the new behavior continues to be confusing after you learn it because there are subtleties. e.g., "which pass gets silenced again?", "oh, right, it's the second one, so if you log a value and render it, the console might show something different than the screen", "what about when you set state in render?", "what about refs?", etc.)
The text was updated successfully, but these errors were encountered: