Why did you render
Monkey patches React to notify you about avoidable re-renders.
README
Why Did You Render
- ``` js
- <BigListPureComponent style={{width: '100%'}}/>
- ```
Setup
- ```
- npm install @welldone-software/why-did-you-render --save-dev
- ```
- ```
- yarn add --dev @welldone-software/why-did-you-render
- ```
- ``` js
- ['@babel/preset-react', {
- runtime: 'automatic',
- development: process.env.NODE_ENV === 'development',
- importSource: '@welldone-software/why-did-you-render',
- }]
- ```
Notice: Create React App (CRA) ^4 does use the automatic JSX transformation.
- ``` js
- import React from 'react';
- if (process.env.NODE_ENV === 'development') {
- const whyDidYouRender = require('@welldone-software/why-did-you-render');
- whyDidYouRender(React, {
- trackAllPureComponents: true,
- });
- }
- ```
*Notice: The library should NEVER be used in production because it slows down React*
- ```tsx
- ///
- ```
- ``` js
- import './wdyr'; // <--- first import
- import 'react-hot-loader';
- import {hot} from 'react-hot-loader/root';
- import React from 'react';
- import ReactDOM from 'react-dom';
- // ...
- import {App} from './app';
- // ...
- const HotApp = hot(App);
- // ...
- ReactDOM.render(<HotApp/>, document.getElementById('root'));
- ```
Custom Hooks
- ``` js
- import React from 'react';
- 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']
- ]
- });
- }
- ```
Notice that there's currently a problem with rewriting exports of imported files in webpack. A quick workaround can help with it: #85 - trackExtraHooks cannot set property.
Read More
Integration With Other Libraries
Sandbox
Tracking Components
- ``` js
- class BigList extends React.Component {
- static whyDidYouRender = true
- render(){
- return (
- //some heavy render you want to ensure doesn't happen if its not necessary
- )
- }
- }
- ```
- ``` js
- const BigListPureComponent = props => (
- <div>
- //some heavy component you want to ensure doesn't happen if its not necessary
- </div>
- )
- BigListPureComponent.whyDidYouRender = true
- ```
- ``` js
- EnhancedMenu.whyDidYouRender = {
- logOnDifferentValues: true,
- customName: 'Menu'
- }
- ```
- ``` js
- render(<Menu a={1}/>)
- render(<Menu a={1}/>)
- ```
- ``` js
- render(<Menu a={1}/>)
- render(<Menu a={2}/>)
- ```
- ``` js
- withPropsOnChange(withPropsOnChange(withStateHandlers(withPropsOnChange(withState(withPropsOnChange(lifecycle(withPropsOnChange(withPropsOnChange(onlyUpdateForKeys(LoadNamespace(Connect(withState(withState(withPropsOnChange(lifecycle(withPropsOnChange(withHandlers(withHandlers(withHandlers(withHandlers(Connect(lifecycle(Menu)))))))))))))))))))))))
- ```
Options
include / exclude
(default: null)
- ``` js
- whyDidYouRender(React, { include: [/^ConnectFunction/] });
- ```
Notice: exclude takes priority over both include and manually set whyDidYouRender =
trackAllPureComponents
(default: false)
Notice: You can exclude the tracking of any specific component with whyDidYouRender = false
trackHooks
(default: true)
trackExtraHooks
(default: [])
- ``` js
- whyDidYouRender(React, {
- trackExtraHooks: [
- // notice that 'useSelector' is a named export
- [ReactRedux, 'useSelector'],
- ]
- });
- ```
There is currently a problem with rewriting exports of imported files in webpack. A workaround is available here: #85 - trackExtraHooks cannot set property
logOwnerReasons
(default: true)
logOnDifferentValues
(default: false)
- ``` js
- render(<BigListPureComponent a={1}/>)
- render(<BigListPureComponent a={2}/>)
- // will only log if you use {logOnDifferentValues: true}
- ```
hotReloadBufferMs
(default: 500)
onlyLogs
(default: false)
collapseGroups
(default: false)
titleColor / diffNameColor / diffPathColor
(default titleColor: '#058')
(default diffNameColor: 'blue')
(default diffPathColor: 'red')
notifier
(default: defaultNotifier that is exposed from the library)
getAdditionalOwnerData
(default: undefined)
Troubleshooting
No tracking
- ``` js
- const HotApp = hot(App);
- HotApp.whyDidYouRender = true;
- ReactDOM.render(<HotApp/>, document.getElementById('root'));
- ReactDOM.render(<HotApp/>, document.getElementById('root'));
- ```
Custom Hooks tracking (like useSelector)
React-Redux connect HOC is spamming the console
- ``` js
- const SimpleComponent = ({a}) => <div data-testid="foo">{a.b}</div>)
- // not before the connect:
- // SimpleComponent.whyDidYouRender = true
- const ConnectedSimpleComponent = connect(
- state => ({a: state.a})
- )(SimpleComponent)
- // after the connect:
- SimpleComponent.whyDidYouRender = true
- ```