왜 '약속'일까?console.log가 아닌 React 컴포넌트에서 두 번 호출된 경우
다음 컴포넌트의 출력이 매우 혼란스럽습니다.
import { StrictMode } from "react"
import ReactDOM from "react-dom"
function Test(): React.ReactElement {
console.log('render')
Promise.resolve()
.then(() => console.log('then ' + Math.random()))
return <></>
}
ReactDOM.render(
<StrictMode>
<Test />
</StrictMode>,
document.getElementById("root")
)
적어도 Chrome 및 Firefox에서는 다음 출력이 생성됩니다.
00:46:30.264 render
00:46:30.267 then 0.5430663800781927
00:46:30.267 then 0.9667426372511254
나는 차라리 같은 수의 메시지를 볼 수 있기를 기대한다.제가 무엇을 빠뜨리고 있나요?
리프로파일: https://codesandbox.io/s/elegant-frost-dmcsl
EDIT: strict 모드가 추가 렌더링으로 이어진다는 것은 알고 있습니다만, 앞에서 설명한 바와 같이 동일한 수의 메시지가 표시됩니다.
EDIT 2: 다음 두 답변 모두 훌륭합니다.@user56reinstatemonica8의 코멘트를 인용하고 싶습니다.
React strict 모드에서는 respect가 렌더링을 여러 번 실행할 수 있으며, 이는 표시되는 내용을 부분적으로 설명할 수 있습니다.
그러나 당신은 그것이 사실인지, 렌더가 여러 번 호출되었는지, 왜 두 번 인쇄되지 않았는지 정확히 알고 있습니다.
React는 콘솔 방식을 다음과 같이 변경합니다.console.log()
경우에 따라서는 로그를 정지합니다.다음은 견적을 제시하겠습니다.
React 17부터 react는 console.log() 등의 콘솔 메서드를 자동으로 변경하여 라이프 사이클 함수에 대한 두 번째 호출 시 로그를 무음화합니다.단, 회피책을 사용할 수 있는 경우에 따라서는 바람직하지 않은 동작이 발생할 수 있습니다.
듣자하니, 그것은 그렇게 하지 않는 것 같다.console.log
Promise 콜백에서 호출됩니다.그러나 렌더에서 호출할 때는 그렇게 됩니다.이에 대한 자세한 내용은 @trincot의 답변을 참조하십시오.
strict 모드가 유효하게 되어 있는 경우(개발 모드에서만) 렌더 함수의 두 번째 실행이 있습니다만, 여기서 설명한 바와 같이 React는 패치를 몽키합니다.console
메서드(개요)disableLogs();
(동기화)가 실행되는 동안 출력되지 않도록 합니다.
이 코드가 삽입된 것을 Changelog에 나타냅니다.packages/react-reconciler/src/ReactFiberBeginWork.js
로그를 일시적으로 억제하려면(코멘트가 표시된 삽입)
if (__DEV__) {
ReactCurrentOwner.current = workInProgress;
setIsRendering(true);
nextChildren = renderWithHooks(
current,
workInProgress,
render,
nextProps,
ref,
renderExpirationTime,
);
if (
debugRenderPhaseSideEffectsForStrictMode &&
workInProgress.mode & StrictMode
) {
disableLogs(); // <--
try { // <--
nextChildren = renderWithHooks(
current,
workInProgress,
render,
nextProps,
ref,
renderExpirationTime,
);
} finally { // <--
reenableLogs(); // <--
} // <--
다음은 실제로 두 번 실행되는 코드 버전입니다.
var i = 0;
var myconsolelog = console.log; // Work around React's monkeypatching
function Test(): React.ReactElement {
i++;
myconsolelog(i + ". render"); // will output twice now!
Promise.resolve(i)
.then((i) => console.log(i + ". then " + Math.random()));
return <></>;
}
이 로그 억제는 정말 잘못된 설계 선택이라고 생각합니다.
혹시 도움이 될지도 모르니까 몽키패치라도 해Object.defineProperties
에 대한 변경을 무시합니다.console
오브젝트, React DOM의 원숭이 패치를 효과적으로 방지합니다.console.log
.
const defineProperties = Object.defineProperties;
Object.defineProperties = function (o, props) {
return o === console ? o : defineProperties(o, props);
};
반드시 개발 모드로 해 주세요(예를 들어 create-react-app의 경우).process.env.NODE_ENV === 'development'
()는, 빌드 )에
언급URL : https://stackoverflow.com/questions/68291908/why-is-promise-then-called-twice-in-a-react-component-but-not-the-console-log
'itsource' 카테고리의 다른 글
부울에서의 ng-filter 필터 (0) | 2023.03.28 |
---|---|
클래스 메서드에서 'this'가 사용되어야 합니다. (0) | 2023.03.28 |
is 키워드는 타이프스크립트에서 어떤 역할을 합니까? (0) | 2023.03.28 |
Angular Material: 매트 셀렉트 기본값 선택 안 함 (0) | 2023.03.28 |
Python에서의 HTTP 응답 해석 (0) | 2023.03.28 |