Skip to content
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

Disable console.logs in the second render pass of DEV mode double render #18547

Merged
merged 3 commits into from Apr 8, 2020

Conversation

@sebmarkbage
Copy link
Member

@sebmarkbage sebmarkbage commented Apr 8, 2020

This disables console.log by temporarily patching the global console object during the second render pass when we double render in strict mode in DEV.

I could go either way on this. It is confusing that it double logs warnings, React, legacy react packages or third-party ones. However, if you do have a problem due to double rendering then you kind of want logs to debug it.

I also uses this override to detect this in our Scheduler.yieldValue helper so that it automatically doesn't double log which makes it easier to write tests that test render phases. This can be done without any internals being exposed so it works to test our build outputs.

The main motivation of this is actually a different PR where I want to double render to expose stack traces. In this case it's extra strange because it's extracting the error stack from the first one that causes new warnings that are not necessarily the same. So I think we need something there. We don't necessarily have to do the same for these ones.

This is ofc not exhaustive since there are so many other side-effects than just logs and you could have other APIs that show logs in UI etc.

@gaearon
Copy link
Member

@gaearon gaearon commented Apr 8, 2020

I was just debugging some internals yesterday and wished we had this.

@codesandbox
Copy link

@codesandbox codesandbox bot commented Apr 8, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit b7e2345:

Sandbox Source
competent-lake-s920v Configuration
@acdlite
acdlite approved these changes Apr 8, 2020
Copy link
Member

@acdlite acdlite left a comment

I only skimmed it

@acdlite
Copy link
Member

@acdlite acdlite commented Apr 8, 2020

Could we do the same for replayFailedUnitOfWorkWithInvokeGuardedCallback?

@@ -149,8 +148,7 @@ describe('ReactDOMFiberAsync', () => {
describe('concurrent mode', () => {
beforeEach(() => {
jest.resetModules();
ReactFeatureFlags = require('shared/ReactFeatureFlags');
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;

This comment has been minimized.

@acdlite

acdlite Apr 8, 2020
Member

Can remove internal suffix now

This comment has been minimized.

@sebmarkbage

sebmarkbage Apr 8, 2020
Author Member

Yea I'll do a follow up to rename all these if I land this. I think the remaining ones are just using the let ops = [] pattern and we can port those.

@sizebot
Copy link

@sizebot sizebot commented Apr 8, 2020

Details of bundled changes.

Comparing: b225d4f...b7e2345

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +0.3% +0.3% 630.4 KB 632.6 KB 132.89 KB 133.29 KB UMD_DEV
react-art.production.min.js 0.0% 0.0% 107.13 KB 107.13 KB 32.46 KB 32.46 KB UMD_PROD
react-art.development.js +0.4% +0.4% 534.92 KB 536.98 KB 115.3 KB 115.72 KB NODE_DEV
react-art.production.min.js 0.0% 0.0% 72.15 KB 72.15 KB 21.66 KB 21.67 KB NODE_PROD
ReactART-dev.js +0.4% +0.3% 596.51 KB 598.69 KB 125.04 KB 125.46 KB FB_WWW_DEV
ReactART-prod.js 0.0% 0.0% 248.21 KB 248.21 KB 41.94 KB 41.94 KB FB_WWW_PROD

scheduler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
scheduler-unstable_mock.development.js +2.4% +2.3% 21.82 KB 22.33 KB 5.22 KB 5.34 KB NODE_DEV
scheduler-unstable_mock.production.min.js 🔺+1.5% 🔺+1.4% 4.65 KB 4.72 KB 1.88 KB 1.9 KB NODE_PROD
SchedulerMock-dev.js +2.3% +2.3% 22.73 KB 23.25 KB 5.36 KB 5.49 KB FB_WWW_DEV
SchedulerMock-prod.js 🔺+0.9% 🔺+1.4% 11.9 KB 12 KB 2.79 KB 2.83 KB FB_WWW_PROD
scheduler-unstable_mock.development.js +2.3% +2.4% 23.41 KB 23.95 KB 5.34 KB 5.46 KB UMD_DEV
scheduler-unstable_mock.production.min.js 🔺+1.5% 🔺+1.3% 4.67 KB 4.74 KB 1.95 KB 1.98 KB UMD_PROD

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.production.min.js 0.0% 0.0% 119.69 KB 119.69 KB 37.52 KB 37.52 KB NODE_PROD
react-dom-test-utils.development.js 0.0% 0.0% 75.12 KB 75.12 KB 20.11 KB 20.11 KB UMD_DEV
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 4.9 KB 4.9 KB 1.64 KB 1.64 KB UMD_DEV
react-dom.profiling.min.js 0.0% 0.0% 123.54 KB 123.54 KB 38.66 KB 38.66 KB NODE_PROFILING
react-dom-server.node.production.min.js 0.0% -0.0% 23.23 KB 23.23 KB 8.65 KB 8.65 KB NODE_PROD
ReactDOMForked-dev.js +0.2% +0.2% 1005.25 KB 1007.43 KB 222.69 KB 223.11 KB FB_WWW_DEV
react-dom-unstable-fizz.node.development.js 0.0% +0.1% 5.16 KB 5.16 KB 1.69 KB 1.69 KB NODE_DEV
react-dom.development.js +0.2% +0.2% 903.52 KB 905.73 KB 198.37 KB 198.78 KB UMD_DEV
react-dom-server.browser.development.js 0.0% 0.0% 155 KB 155 KB 39.38 KB 39.38 KB UMD_DEV
react-dom.production.min.js 0.0% 0.0% 119.55 KB 119.55 KB 38.25 KB 38.25 KB UMD_PROD
react-dom.profiling.min.js 0.0% 0.0% 123.27 KB 123.27 KB 39.48 KB 39.48 KB UMD_PROFILING
react-dom.development.js +0.2% +0.2% 860.16 KB 862.22 KB 195.9 KB 196.31 KB NODE_DEV
react-dom-server.browser.development.js 0.0% 0.0% 145.85 KB 145.85 KB 38.63 KB 38.63 KB NODE_DEV
ReactDOM-dev.js +0.2% +0.2% 1005.25 KB 1007.43 KB 222.69 KB 223.11 KB FB_WWW_DEV
ReactDOMServer-dev.js 0.0% 0.0% 157.98 KB 157.98 KB 39.92 KB 39.92 KB FB_WWW_DEV
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 56.1 KB 56.1 KB 13.84 KB 13.84 KB UMD_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 9.98 KB 9.98 KB 3.36 KB 3.36 KB UMD_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 53.2 KB 53.2 KB 13.64 KB 13.64 KB NODE_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 9.73 KB 9.73 KB 3.25 KB 3.25 KB NODE_PROD

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.development.js +0.4% +0.4% 574.28 KB 576.34 KB 121.48 KB 121.91 KB NODE_DEV
react-reconciler-reflection.production.min.js 0.0% 🔺+0.1% 2.57 KB 2.57 KB 1.08 KB 1.09 KB NODE_PROD

Size changes (stable)

Generated by 🚫 dangerJS against b7e2345

@sizebot
Copy link

@sizebot sizebot commented Apr 8, 2020

Details of bundled changes.

Comparing: b225d4f...b7e2345

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +0.4% +0.3% 650.67 KB 652.97 KB 136.59 KB 136.99 KB UMD_DEV
react-art.production.min.js 0.0% 0.0% 109.74 KB 109.74 KB 33.13 KB 33.13 KB UMD_PROD
react-art.development.js +0.4% +0.3% 554.4 KB 556.54 KB 119.07 KB 119.47 KB NODE_DEV
react-art.production.min.js 0.0% 0.0% 74.71 KB 74.71 KB 22.33 KB 22.33 KB NODE_PROD
ReactART-dev.js +0.4% +0.3% 586.45 KB 588.62 KB 123.06 KB 123.47 KB FB_WWW_DEV

scheduler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
scheduler-unstable_mock.development.js +2.3% +2.4% 23.42 KB 23.96 KB 5.34 KB 5.47 KB UMD_DEV
scheduler-unstable_mock.production.min.js 🔺+1.5% 🔺+1.3% 4.69 KB 4.76 KB 1.96 KB 1.99 KB UMD_PROD
scheduler-tracing.development.js 0.0% +0.1% 8.81 KB 8.81 KB 1.79 KB 1.79 KB NODE_DEV
scheduler-unstable_mock.development.js +2.4% +2.4% 21.83 KB 22.34 KB 5.23 KB 5.35 KB NODE_DEV
scheduler-unstable_mock.production.min.js 🔺+1.5% 🔺+1.3% 4.66 KB 4.73 KB 1.89 KB 1.91 KB NODE_PROD
SchedulerMock-dev.js +2.3% +2.3% 22.73 KB 23.25 KB 5.36 KB 5.49 KB FB_WWW_DEV
SchedulerMock-prod.js 🔺+0.9% 🔺+1.4% 11.9 KB 12 KB 2.79 KB 2.83 KB FB_WWW_PROD
scheduler.development.js 0.0% 0.0% 23.23 KB 23.23 KB 6.02 KB 6.02 KB NODE_DEV
scheduler.production.min.js 0.0% -0.0% 4.94 KB 4.94 KB 1.98 KB 1.98 KB NODE_PROD

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom-server.browser.production.min.js 0.0% 0.0% 23.39 KB 23.39 KB 8.6 KB 8.6 KB UMD_PROD
react-dom.profiling.min.js 0.0% 0.0% 127.81 KB 127.81 KB 39.89 KB 39.89 KB NODE_PROFILING
ReactDOM-dev.js +0.2% +0.2% 977.37 KB 979.55 KB 216.7 KB 217.13 KB FB_WWW_DEV
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 4.43 KB 4.43 KB 1.55 KB 1.55 KB NODE_DEV
react-dom-test-utils.development.js 0.0% 0.0% 75.14 KB 75.14 KB 20.11 KB 20.12 KB UMD_DEV
ReactDOMTesting-prod.js 0.0% 0.0% 393.2 KB 393.2 KB 71.65 KB 71.65 KB FB_WWW_PROD
ReactDOMTesting-profiling.js 0.0% 0.0% 393.2 KB 393.2 KB 71.65 KB 71.65 KB FB_WWW_PROFILING
react-dom-server.browser.development.js 0.0% 0.0% 147.36 KB 147.36 KB 38.84 KB 38.84 KB NODE_DEV
react-dom.development.js +0.2% +0.2% 933.35 KB 935.65 KB 203.65 KB 204.05 KB UMD_DEV
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 56.11 KB 56.11 KB 13.85 KB 13.85 KB UMD_DEV
react-dom.production.min.js 0.0% 0.0% 123.63 KB 123.63 KB 39.42 KB 39.42 KB UMD_PROD
ReactDOMForked-dev.js +0.2% +0.2% 977.37 KB 979.55 KB 216.7 KB 217.13 KB FB_WWW_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 10 KB 10 KB 3.36 KB 3.36 KB UMD_PROD
ReactDOMServer-dev.js 0.0% 0.0% 154.48 KB 154.48 KB 38.97 KB 38.97 KB FB_WWW_DEV
react-dom.profiling.min.js 0.0% 0.0% 127.47 KB 127.47 KB 40.63 KB 40.63 KB UMD_PROFILING
react-dom.development.js +0.2% +0.2% 888.75 KB 890.89 KB 201.17 KB 201.58 KB NODE_DEV
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 53.21 KB 53.21 KB 13.65 KB 13.65 KB NODE_DEV
react-dom.production.min.js 0.0% 0.0% 123.83 KB 123.83 KB 38.62 KB 38.62 KB NODE_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-prod.js 0.0% -0.0% 270.91 KB 270.91 KB 46.57 KB 46.57 KB RN_OSS_PROD
ReactFabric-prod.js 0.0% 0.0% 262.89 KB 262.89 KB 45.05 KB 45.05 KB RN_OSS_PROD
ReactFabric-dev.js +0.3% +0.3% 637.88 KB 639.96 KB 136.21 KB 136.64 KB RN_FB_DEV
ReactNativeRenderer-dev.js 0.0% 0.0% 653.75 KB 653.75 KB 140.33 KB 140.33 KB RN_OSS_DEV
ReactFabric-profiling.js 0.0% 0.0% 274.42 KB 274.42 KB 47.25 KB 47.25 KB RN_FB_PROFILING
ReactNativeRenderer-dev.js +0.3% +0.3% 656.16 KB 658.24 KB 140.65 KB 141.08 KB RN_FB_DEV
ReactFabric-dev.js 0.0% 0.0% 635.46 KB 635.46 KB 135.9 KB 135.9 KB RN_OSS_DEV

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler-reflection.production.min.js 0.0% 🔺+0.1% 2.58 KB 2.58 KB 1.09 KB 1.09 KB NODE_PROD
react-reconciler.development.js +0.4% +0.3% 596.12 KB 598.26 KB 125.76 KB 126.17 KB NODE_DEV

ReactDOM: size: 0.0%, gzip: 0.0%

Size changes (experimental)

Generated by 🚫 dangerJS against b7e2345

@sebmarkbage
Copy link
Member Author

@sebmarkbage sebmarkbage commented Apr 8, 2020

Could we do the same for replayFailedUnitOfWorkWithInvokeGuardedCallback?

I think we probably could but that one was kind of so that you could break on the exception. The problem then is your logs are disabled while on your break point. That seems highly confusing. I'm not sure that's the right call.

);
disableLogs();
try {
value = renderWithHooks(

This comment has been minimized.

@acdlite

acdlite Apr 8, 2020
Member

I could foresee some confusion if the logs don't correspond to the value that is returned. It usually doesn't matter because it's supposed to be pure, but in the case where it's not, you might use console to debug it. So maybe they should be disabled for the first pass instead of the second.

This comment has been minimized.

@sebmarkbage

sebmarkbage Apr 8, 2020
Author Member

So I was actually surprised that we used the second value. I was thinking we should ignore the second value like we do for class constructors.

This comment has been minimized.

@sebmarkbage

sebmarkbage Apr 8, 2020
Author Member

In my other PR's replaying I have to ignore it because I force an error inside the function. Similarly the react-debug-tools for Hooks debugging it's just replayed stand-alone.

Doesn't necessarily mean we have to do the same here. I guess that's how I look at these.

This comment has been minimized.

@acdlite

acdlite Apr 8, 2020
Member

It's intentional because the children are bound to the work-in-progress fiber via the queue object via the dispatch method, and renderWithHooks mutates the fiber.

It was a very confusing bug when we found it :D

This comment has been minimized.

@acdlite

acdlite Apr 8, 2020
Member

This one: #14698

This comment has been minimized.

@sebmarkbage

sebmarkbage Apr 8, 2020
Author Member

I could go either way on if the second render should process the update queue and even leave any side-effects. :)

This comment has been minimized.

@sebmarkbage

sebmarkbage Apr 8, 2020
Author Member

Maybe the second render should have a different dispatcher that warns if you call setState again since you shouldn't call setState again for the same input.

This comment has been minimized.

@acdlite

acdlite Apr 8, 2020
Member

I could go either way on if the second render should process the update queue and even leave any side-effects :)

It can work but it needs to include internal mutations/side-effects too. We'd have to make it so that renderWithHooks does not mutate any of the fiber fields. Or stash the result of the first pass (memoizedState, expirationTime, effectTag) before doing the second pass and then restore them.

This comment has been minimized.

@acdlite

acdlite Apr 8, 2020
Member

Maybe the second render should have a different dispatcher that warns if you call setState again since you shouldn't call setState again for the same input.

Oh I didn't see that. Yeah I think that would work. Just call the component again with a special dispatcher that doesn't mutate anything.

This comment has been minimized.

@bvaughn

bvaughn Apr 9, 2020
Contributor

Maybe the second render should have a different dispatcher that warns if you call setState again since you shouldn't call setState again for the same input.

I might be misunderstanding this comment, but if the second call has state updates already applied, then we might miss out on triggering the observable side effects in the first place (e.g. like something that happens only when props/state meet a certain criteria).

@acdlite
Copy link
Member

@acdlite acdlite commented Apr 8, 2020

The problem then is your logs are disabled while on your break point

I was thinking you would disable the logs during the first pass and enable them for the second. In the case of an error, the second pass would use invokeGuardedCallback.

@sebmarkbage
Copy link
Member Author

@sebmarkbage sebmarkbage commented Apr 8, 2020

I was thinking you would disable the logs during the first pass and enable them for the second. In the case of an error, the second pass would use invokeGuardedCallback.

That would mean that we would have to always replay the second pass. At least as long as there's any log. Since most of the time when nothing throws or if it's just throwing a Promise, there wouldn't be a second pass.

@acdlite
Copy link
Member

@acdlite acdlite commented Apr 8, 2020

That would mean that we would have to always replay the second pass.

That seems fine? Isn't the only new case promises?

@sebmarkbage
Copy link
Member Author

@sebmarkbage sebmarkbage commented Apr 8, 2020

That seems fine? Isn't the only new case promises?

No if we disable the logs we'd have to detect that we had silenced a log and replay - even if there's nothing thrown at all. So any little log would severely slow down debugging.

We can't replay the logs later because it would give them the wrong stacks frames in the devtools.

@acdlite
Copy link
Member

@acdlite acdlite commented Apr 8, 2020

I'm confused because we already replay the methods in dev. I don't get what's getting slower.

@sebmarkbage
Copy link
Member Author

@sebmarkbage sebmarkbage commented Apr 8, 2020

Hm. I was under the impression that we replay the whole render but I guess it's just the begin phase. Is that even safe from a resuming perspective? Seems like we'd have a lot of latent bugs there. Probably SuspenseList.

@sebmarkbage
Copy link
Member Author

@sebmarkbage sebmarkbage commented Apr 8, 2020

It seems like these two should just use the same mechanism. If the first pass errors, then we do the double render pass in invokeGuardedCallback

@sebmarkbage
Copy link
Member Author

@sebmarkbage sebmarkbage commented Apr 8, 2020

We can do that in a follow up if we decide to land this. For now we need to decide on this (yes or no) to unblock the production stacks PR.

@bvaughn
bvaughn approved these changes Apr 8, 2020
@sebmarkbage
Copy link
Member Author

@sebmarkbage sebmarkbage commented Apr 8, 2020

One fatal flaw of silencing the first pass is warning deduping. Almost none of our warnings would show up as it currently stands and also true if others use the same technique.

@sebmarkbage sebmarkbage changed the title [RFC] Disable console.logs in the second render pass of DEV mode double render Disable console.logs in the second render pass of DEV mode double render Apr 8, 2020
@sebmarkbage sebmarkbage merged commit 5474a83 into facebook:master Apr 8, 2020
31 checks passed
31 checks passed
ci/circleci: NODE_ENV_production_yarn_test_www Your tests passed on CircleCI!
Details
ci/circleci: NODE_ENV_production_yarn_test_www_variant Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_NODE_ENV_production_yarn_test_www Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_NODE_ENV_production_yarn_test_www_variant Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_build Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_test Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_test_build Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_test_build_prod Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_test_dom_fixtures Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_test_persistent Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_test_prod Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_test_www Your tests passed on CircleCI!
Details
ci/circleci: RELEASE_CHANNEL_stable_yarn_test_www_variant Your tests passed on CircleCI!
Details
ci/circleci: build_devtools_and_process_artifacts Your tests passed on CircleCI!
Details
ci/circleci: process_artifacts Your tests passed on CircleCI!
Details
ci/circleci: process_artifacts_experimental Your tests passed on CircleCI!
Details
ci/circleci: setup Your tests passed on CircleCI!
Details
ci/circleci: sizebot_experimental Your tests passed on CircleCI!
Details
ci/circleci: sizebot_stable Your tests passed on CircleCI!
Details
ci/circleci: yarn_build Your tests passed on CircleCI!
Details
ci/circleci: yarn_flow Your tests passed on CircleCI!
Details
ci/circleci: yarn_lint Your tests passed on CircleCI!
Details
ci/circleci: yarn_lint_build Your tests passed on CircleCI!
Details
ci/circleci: yarn_test Your tests passed on CircleCI!
Details
ci/circleci: yarn_test_build Your tests passed on CircleCI!
Details
ci/circleci: yarn_test_build_devtools Your tests passed on CircleCI!
Details
ci/circleci: yarn_test_build_prod Your tests passed on CircleCI!
Details
ci/circleci: yarn_test_prod Your tests passed on CircleCI!
Details
ci/circleci: yarn_test_www Your tests passed on CircleCI!
Details
ci/circleci: yarn_test_www_variant Your tests passed on CircleCI!
Details
ci/codesandbox Building packages succeeded.
Details
@sebmarkbage
Copy link
Member Author

@sebmarkbage sebmarkbage commented Apr 9, 2020

This actually revealed that we're calling the fake setState updaters for classes first and silencing the warnings inside of them as a result.

@orestis
Copy link

@orestis orestis commented May 12, 2020

I know this is in the experimental branch and I'm not supposed to use it, but I found this super confusing when I was trying to figure out what was going on in some lifecycles :)

@gaearon
Copy link
Member

@gaearon gaearon commented May 12, 2020

Yeah, I feel that. I could go either way on this.

If you don't know what's happening, this makes it doubly confusing.

But if you know what's happening, then not having this is annoying because you can't use console.log to debug things in a sequence. It's just too noisy.

@orestis
Copy link

@orestis orestis commented May 12, 2020

My underlying issue is that I had some other render side-effects that I thought were idempotent (useRef) but turns out not -- and the first instinct to pull out console.log made me super confused.

As always in software, there's the possibility of making this configurable, perhaps opt-out with a small start-up warning message letting people know it's a thing? I mean, the double-render behaviour is mentioned in the docs but I'm pretty sure many people miss it.

@bvaughn
Copy link
Contributor

@bvaughn bvaughn commented May 12, 2020

perhaps opt-out with a small start-up warning message letting people know it's a thing?

I think console messages like this are kind of traps. They seem really useful- and often are, initially, but then they can get really annoying because after you've seen them and know what's going on- the console message is still always there cluttering up your log.

Even if we could only show them exactly once (say using a mechanism like DevTools and localStorage) there's a chance you would not see them that one time, because people aren't always staring at their console- only when they're actively using it to debug.

@gaearon
Copy link
Member

@gaearon gaearon commented May 12, 2020

The problem with console messages on startup is that people who need them the most won't read them, and they're noise for everybody else.

@jamesknelson
Copy link

@jamesknelson jamesknelson commented Aug 20, 2020

I feel like some kind of warning would be really nice here.

I've been pulling my hair out the last few days trying to figure out why something seemed to be running twice, while the console logs seemed to show that it was only running once. It got especially confusing as logs in async code triggered by the render were still appearing twice, making it seem like the issue was async related. I only managed to figure out what was going on by grepping for console in react-dom.development.js.

I'm not sure exactly what the best way to warn developers is, but I'd wager most developers wouldn't expect a global like the console to change without some kind of warning.

Edit:

One suggestion would be for an export from react-dom that lets you enable/disable this behavior. This would make it clearer to new developers that some things are being called twice, while also avoiding the pitfalls around trying to teach the behavior in the console. It could also be included in CRA's template, which seems like a pretty suitable place to let developers know how to use/disable it.

For what it's worth, the issue for me ended up being that I'd accidentally ended up with a side effect in useMemo().

@eps1lon
Copy link
Collaborator

@eps1lon eps1lon commented Aug 20, 2020

One suggestion would be for an export from react-dom that lets you enable/disable this behavior.

I think the plan is to add a devtools option for it. See https://twitter.com/dan_abramov/status/1292959451415302144.

Opening a new feature request for devtools would help with some context why the current behavior is problematic and why the previous behavior was problematic as well. Otherwise comments in an already merged PR might get lost.

@bvaughn
Copy link
Contributor

@bvaughn bvaughn commented Aug 20, 2020

There's some prior art here, as DevTools already overrides the console to add component stacks (if the option is enabled).

Screen Shot 2020-08-20 at 9 05 15 AM

Might be worth putting together a detailed proposal of how this should work (as a new GitHub issue).

@joepuzzo
Copy link

@joepuzzo joepuzzo commented Nov 2, 2020

IMO this is kind of crazy. In order to teach others of this behavior I would previously create a simple example in code sandbox and log in a use state.

useState(() => console.log('Init'))

Most devs ( myself included ) "learn by logging". Now they may be scratching their heads for hours until they stumble upon an article or post that describes their code is executing two times. This needs to be more transparent.

@matthewma7
Copy link

@matthewma7 matthewma7 commented Nov 13, 2020

Didn't aware the strict mode is double rendering, this change cost me last night chasing down what happened.
Instead of muting the console.log, could we monkey patch the log and append something like "Strict Mode double render" to the beginning of the console.log?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

You can’t perform that action at this time.