Welldone Software의 원숭이 패치 why-did-you-render
잠재적으로 피할 수 있는 재렌더링에 대해 알려주는 React
. ( React Native
에서도 작동합니다.)
예를 들어, style={{width: '100%'}}
큰 순수 구성 요소에 전달하면 모든 요소 생성 시 항상 다시 렌더링됩니다.
<BigListPureComponent 스타일={{너비: '100%'}}/>
또한 특정 구성 요소가 다시 렌더링되는 시기와 이유를 간단히 추적하는 데 도움이 될 수 있습니다.
최신 버전의 라이브러리는 React@18
로만 테스트되었습니다(단위 테스트 및 E2E). React 17 및 16의 경우 버전 @^7을 사용하세요.
npm install @welldone-software/why-did-you-render --save-dev
또는
yarn add --dev @welldone-software/why-did-you-render
automatic
JSX 변환을 사용하는 경우 라이브러리를 가져오기 소스로 설정하고 preset-react
development
모드인지 확인하세요.
['@babel/preset-react', { 런타임: '자동', 개발: process.env.NODE_ENV === '개발', importSource: '@welldone-software/why-did-you-render',}]
불행하게도, 즉시 사용 가능한 반응 네이티브와 함께 제공되는 metro-react-native-babel-preset
에서는 babel/plugin-transform-react-jsx
플러그인의 옵션을 변경할 수 없습니다. 아래 나열된 옵션과 함께 플러그인을 추가하고 평소대로 반응 네이티브 패키저를 시작하세요. babel의 기본 환경은 "development"입니다. React-Native로 작업할 때 Expo를 사용하지 않는 경우 다음 방법이 도움이 될 것입니다.
module.exports = { 사전 설정: ['module:metro-react-native-babel-preset'], env: { 개발: { 플러그인: [['@babel/plugin-transform-react-jsx', { 런타임: ' 클래식' }]], }, },}
babel-preset-expo
통해 @babel/preset-react
에 매개변수를 전달할 수 있습니다.
// babel.config.jsmodule.exports = function (api) { api.cache(true); return { 사전 설정: [ [ "babel-preset-expo", { jsxImportSource: "@welldone-software/why-did-you-render", }, ], ], };};
참고: Create React App(CRA) ^4는
automatic
JSX 변환을 사용합니다. CRA로 이 단계를 수행하는 방법에 대한 다음 설명을 참조하세요.
wdyr.js
파일을 생성하고 이를 애플리케이션의 첫 번째 가져오기 로 가져옵니다.
wdyr.js
:
import React from 'react';if (process.env.NODE_ENV === 'development') { const WhyDidYouRender = require('@welldone-software/why-did-you-render'); WhyDidYouRender(React, { trackAllPureComponents: true, });}
주의 사항: 라이브러리는 React 속도를 저하시키므로 프로덕션 환경에서는 절대 사용해서는 안 됩니다.
Typescript에서 wdyr.ts 파일을 호출하고 파일 맨 위에 다음 줄을 추가하여 패키지 유형을 가져옵니다.
/// <reference type="@welldone-software/why-did-you-render" />
첫 번째 가져오기로 wdyr
가져옵니다( react-hot-loader
이전에도).
index.js
:
import './wdyr'; // <--- 먼저 importimport 'react-hot-loader'; import {hot} from 'react-hot-loader/root'; import React from 'react'; import ReactDOM from 'react-dom';// . ..'./app'에서 {App} 가져오기;// ...const HotApp = hot(App);// ...ReactDOM.render(<HotApp/>, document.getElementById('root'));
우리가 제안한 대로 trackAllPureComponents
사용하면 모든 순수 구성 요소(React.PureComponent 또는 React.memo)가 추적됩니다.
그렇지 않으면 추적하려는 구성 요소 클래스/함수에 whyDidYouRender = true
추가하세요. (fe Component.whyDidYouRender = true
)
추적되는 항목에 대한 자세한 내용은 구성 요소 추적에서 확인할 수 있습니다.
WDYR 로그를 볼 수 없나요? 문제 해결 섹션을 확인하거나 문제를 검색하세요.
또한 trackExtraHooks
사용하여 사용자 정의 후크 추적이 가능합니다. 예를 들어 React Redux에서 useSelector
추적하려는 경우:
wdyr.js
:
import React from 'react';// 반응 네이티브의 경우 // process.env.NODE_ENV 대신 __DEV__ 플래그를 사용하는 것이 좋습니다 === 'development'if (process.env.NODE_ENV === 'development') { const WhyDidYouRender = require('@welldone-software/why-did-you-render'); const ReactRedux = require('react-redux'); WhyDidYouRender(React, { trackAllPureComponents: true, trackExtraHooks: [ [ReactRedux, 'useSelector'] ] });}
현재
webpack
에서 가져온 파일의 내보내기를 다시 작성하는 데 문제가 있습니다. 빠른 해결 방법이 도움이 될 수 있습니다: #85 - trackExtraHooks는 속성을 설정할 수 없습니다.
Mr. Big Pure React 컴포넌트를 렌더링한 이유는 무엇인가요???
이 라이브러리가 도움이 될 수 있는 일반적인 수정 시나리오
React Hooks - 후크 문제 이해 및 수정
왜 Render v4가 출시되었나요? - TypeScript 지원, 사용자 정의 후크 추적(React-Redux의 useSelector와 같은), 모든 순수 구성 요소 추적.
Next.js 예
후크가 있는 React-Redux
Mobx는 현재 지원되지 않습니다.
@allen-hsu가 만든 React-Native 플리퍼 플러그인
공식 샌드박스에서 라이브러리를 테스트할 수 있습니다.
후크 추적 기능이 있는 또 다른 공식 샌드박스
trackAllPureComponents: true
옵션을 사용하면 모든 순수 구성요소(React.PureComponent 또는 React.memo)를 추적할 수 있습니다.
다음과 같이 whyDidYouRender
를 설정하여 원하는 구성 요소를 수동으로 추적할 수도 있습니다.
class BigList extends React.Component { static WhyDidYouRender = true render(){ return ( //필요하지 않은 경우 발생하지 않도록 하려는 일부 무거운 렌더링 ) }}
또는 기능적 구성요소의 경우:
const BigListPureComponent = props => ( <div> //필요하지 않은 경우 발생하지 않도록 하고 싶은 일부 무거운 구성 요소 </div>)BigListPureComponent.whyDidYouRender = true
또한 객체를 전달하여 고급 추적 설정을 지정할 수도 있습니다.
EnhancedMenu.whyDidYouRender = { logOnDifferentValues: true, customName: '메뉴'}
logOnDifferentValues
:
일반적으로 props/state 트리거 알림의 동일한 값으로 인해 발생하는 다시 렌더링만 가능합니다.
render(<메뉴 a={1}/>)render(<메뉴 a={1}/>)
이 옵션은 다른 props/state로 인해 발생하더라도 알림을 트리거합니다(따라서 "합법적인" 재렌더링으로 인해).
render(<메뉴 a={1}/>)render(<메뉴 a={2}/>)
customName
:
때로는 구성 요소의 이름이 누락되거나 매우 불편할 수 있습니다. 예를 들어:
withPropsOnChange(withPropsOnChange(withStateHandlers(withPropsOnChange(withState(withPropsOnChange(lifecycle(withPropsOnChange(withPropsOnChange(withPropsOnChange(onlyUpdateForKeys(LoadNamesp ace(Connect(withState(withState(withPropsOnChange(lifecycle(withPropsOnChange(withHandlers(withHandlers(withHandlers(withHandlers(withHandlers(Connect(lifecycle(Menu))))))))))))))))))))))
선택적으로 options
두 번째 매개변수로 전달할 수 있습니다. 다음 옵션을 사용할 수 있습니다.
include: [RegExp, ...]
(기본적으로 null
)
exclude: [RegExp, ...]
(기본적으로 null
)
trackAllPureComponents: false
trackHooks: true
trackExtraHooks: []
logOwnerReasons: true
logOnDifferentValues: false
hotReloadBufferMs: 500
onlyLogs: false
collapseGroups: false
titleColor
diffNameColor
diffPathColor
notifier: ({Component, displayName, hookName, prevProps, prevState, prevHook, nextProps, nextState, nextHook, reason, options, ownerDataMap}) => void
getAdditionalOwnerData: (element) => {...}
null
) include
및 exclude
옵션을 사용하여 displayName별로 구성 요소 추적을 포함하거나 제외할 수 있습니다.
예를 들어 다음 코드는 이전 React-Redux로 인해 발생한 모든 중복된 다시 렌더링을 추적하는 데 사용됩니다.
WhyDidYouRender(React, { include: [/^ConnectFunction/] });
참고: 제외는
include
및 수동 설정보다 우선합니다.whyDidYouRender =
false
) 모든 순수 구성 요소( React.memo
및 React.PureComponent
구성 요소 모두)를 추적할 수 있습니다.
주의 사항:
whyDidYouRender = false
사용하면 특정 구성 요소의 추적을 제외할 수 있습니다.
true
)후크 변경 사항 추적을 끌 수 있습니다.
후크 문제를 이해하고 수정합니다.
[]
)사용자 정의 후크 추적:
WhyDidYouRender(React, { trackExtraHooks: [ // 'useSelector'는 명명된 내보내기라는 점에 유의하세요. [ReactRedux, 'useSelector'], ]});
현재 webpack에서 가져온 파일의 내보내기를 다시 작성하는 데 문제가 있습니다. 해결 방법은 다음에서 확인할 수 있습니다. #85 - trackExtraHooks는 속성을 설정할 수 없습니다.
true
)다시 렌더링 문제를 해결하는 한 가지 방법은 구성 요소 소유자가 다시 렌더링하지 못하도록 방지하는 것입니다.
이 옵션은 기본적으로 true
이며 소유자 구성 요소가 다시 렌더링되는 이유를 볼 수 있습니다.
false
)일반적으로 피할 수 있었던 구성 요소 다시 렌더링에 대한 로그만 필요합니다.
이 옵션을 사용하면 모든 재렌더링을 추적할 수 있습니다.
예를 들어:
render(<BigListPureComponent a={1}/>)render(<BigListPureComponent a={2}/>)// {logOnDifferentValues: true}를 사용하는 경우에만 기록됩니다.
500
)핫 리로드가 감지된 후 업데이트를 무시하는 시간(밀리초)입니다.
핫 리로드가 감지되면 콘솔에 스팸을 보내지 않도록 hotReloadBufferMs
에 대한 모든 업데이트를 무시합니다.
false
) console.group
사용하여 로그를 그룹화하지 않으려면 간단한 로그로 인쇄할 수 있습니다.
false
)그룹화된 로그는 접을 수 있습니다.
'#058'
)'blue'
)'red'
)콘솔 알림에 사용되는 색상을 제어합니다.
기본 알리미가 필요에 맞지 않는 경우 사용자 정의 알리미를 생성할 수 있습니다.
undefined
)원래 반응 요소에서 추가 데이터를 수집하는 함수를 제공할 수 있습니다. 이 함수에서 반환된 개체는 나중에 알리미 함수 재정의 내에서 액세스할 수 있는 ownerDataMap에 추가됩니다.
프로덕션 중인 경우 WDYR이 비활성화되었을 수 있습니다.
추적되는 구성 요소가 없을 수도 있습니다.
추적 구성 요소를 다시 한 번 확인하세요.
trackAllPureComponents: true
사용하여 순수 구성 요소만 추적하는 경우 (React.PureComponent 또는 React.memo) 중 하나만 추적하게 되며, 순수 구성 요소가 하나도 없어 추적되지 않을 수도 있습니다.
어쩌면 당신에게는 문제가 없을 수도 있습니다.
진입점에서 전체 앱을 임시로 두 번 렌더링하여 문제를 발생시켜 보세요.
index.js
:
const HotApp = hot(App);HotApp.whyDidYouRender = true;ReactDOM.render(<HotApp/>, document.getElementById('root'));ReactDOM.render(<HotApp/>, document.getElementById('root') );
현재 webpack
에서 가져온 파일의 내보내기를 다시 작성하는 데 문제가 있습니다. 빠른 해결 방법이 도움이 될 수 있습니다: #85 - trackExtraHooks는 속성을 설정할 수 없습니다.
connect
HOC가 콘솔에 스팸을 보내고 있습니다. connect
정적을 호이스트하기 때문에 내부 컴포넌트에 WDYR을 추가하면 복잡한 Hook이 실행되는 HOC 컴포넌트에도 추가됩니다.
이 문제를 해결하려면 연결 후 구성 요소에 whyDidYouRender = true
정적을 추가하세요.
const SimpleComponent = ({a}) => <div data-testid="foo">{ab}</div>) // 연결 전이 아님: // SimpleComponent.whyDidYouRender = true const ConnectedSimpleComponent = connect( state => ({a: state.a}) )(SimpleComponent) // 연결 후: SimpleComponent.whyDidYouRender = true
라이브러리의 소스맵을 보려면 source-map-loader를 사용하세요.
다음 이전 작업에서 영감을 얻었습니다.
github.com/maicki/why-did-you-update(더 이상 공개되지 않음)는 한동안 유지할 기회가 있었습니다.
https://github.com/garbles/why-did-you-update 여기서 React 성능 디버깅에 대한 심층 분석이 아이디어로 인정됩니다.
이 라이브러리는 MIT 라이센스를 받았습니다.