Issue 1:
React version: 17.0.2

Steps To Reproduce

The following minimal repro sample is used to indicate a props change in a component:

import React from "react";

export default function App() {
const [a, setA] = React.useState("a");

return (
<>
<Test a={a} />
<button onClick={() => setA((oldA) => (oldA === "a" ? "b" : "a"))}>
Test
</button>
</>
);
}

const Test = ({ a }) => {
const oldRef = React.useRef(a);

const hasChanged = oldRef.current !== a;
if (hasChanged) {
oldRef.current = a;
}

const changedText = hasChanged ? "yes" : "no";
console.log("Changed: ", changedText);

return (
<>
<div>{a}</div>
<div>Changed: {changedText}</div>
</>
);
};

Clicking the "Test" button prints the value "Changed: yes" to the console, while React renders "no":

Note: this works as expected if I remove the <StrictMode> wrapper in index.js.

Link to code example: https://codesandbox.io/s/youthful-jang-2xw3i?file=/src/App.js

The current behavior

"Changed: yes" in printed to console, but "Changed: no" is rendered by React.

The expected behavior

"Changed: yes" in printed to console, "Changed: yes" is rendered by React.

Issue 2:
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.:

#20835

#20982

#20367

#20090

#21178

#21126

#20851

#20575

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:

Anecdotally, it's a recurring source of confusion within my company, much more so than the old behavior was. It's also probably the source of the most "oh, that's weird" reactions (vs. "oh, I get it now") when explained, compared with other React nuances.

The change was only released 8 months ago and there are already many GitHub issues expressing confusion about it, seemingly more than there ever were for the old behavior. (There used to be more instances where people weren't aware that strict mode double-invokes components, but it's not that the new behavior makes this any more clear, it just means that fewer people are now learning this fact, which doesn't seem good?) The rate of new issues also doesn't seem to be slowing as was hypothesized.

The implementing PR (#18547) currently has 19 downvotes vs. 2 upvotes. Obviously people who dislike the change are more likely to downvote, but PRs are rarely this controversial and in fact this is the most downvoted non-docs PR in the whole repo.

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:

Does my perspective on the community reaction align with your perception?

Have you observed a different reaction internally at FB?

In aggregate, does any of this change your original perspective at all?

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.)