# Repository: welldone-software/why-did-you-render
# Stars: 12456
## README.md
# Why Did You Render
[](https://badge.fury.io/js/%40welldone-software%2Fwhy-did-you-render)
[](https://github.com/welldone-software/why-did-you-render/actions/workflows/main.yml)
[](https://github.com/welldone-software/why-did-you-render/blob/master/LICENSE)
[](https://snyk.io/advisor/npm-package/@welldone-software/why-did-you-render)
[](https://coveralls.io/github/welldone-software/why-did-you-render?branch=add-e2e-tests-using-cypress)
`why-did-you-render` by [Welldone Software](https://welldone.software/) monkey patches **`React`** to notify you about potentially avoidable re-renders. (Works with **`React Native`** as well.)
For example, if you pass `style={{width: '100%'}}` to a big memo component it would always re-render on every element creation:
```jsx
```
It can also help you to simply track when and why a certain component re-renders.
> [!CAUTION]
> The library was not tested with [React Compiler](https://react.dev/learn/react-compiler) at all. I believe it's completely incompatible with it.
> [!CAUTION]
> Not all re-renders are *"bad"*. Sometimes shenanigan to reduce re-renders can either hurt your App's performance or have a negligible effect, in which case it would be just a waste of your efforts, and complicate your code. Try to focus on heavier components when optimizing and use the [React DevTools Profiler](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html) to measure the effects of any changes.
> [!NOTE]
I've joined the React team, specifically working on React tooling. This role has opened up exciting opportunities to enhance the developer experience for React users— and your input could offer valuable insights to help me with this effort. Please join the conversation in the [discussion thread](https://github.com/welldone-software/why-did-you-render/discussions/309)!
## Setup
The latest version of the library was tested [(unit tests and E2E)]((https://travis-ci.com/welldone-software/why-did-you-render.svg?branch=master)) with **`React@19`** only.
* [For `React 18`, please see the readme for version @^8](https://github.com/welldone-software/why-did-you-render/tree/version-8).
* [For `React 17` and `React 16`, please see the readme for version @^7](https://github.com/welldone-software/why-did-you-render/tree/version-7).
```
npm install @welldone-software/why-did-you-render --save-dev
```
or
```
yarn add @welldone-software/why-did-you-render -D
```
Set the library to be the React's importSource and make sure `preset-react` is in `development` mode.
This is because `React 19` requires using the `automatic` [JSX transformation](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html).
```js
['@babel/preset-react', {
runtime: 'automatic',
development: process.env.NODE_ENV === 'development',
importSource: '@welldone-software/why-did-you-render',
}]
```
### React Native
#### Bare workflow
Add the plugin as listed below and start react-native packager as usual. Default env for babel is "development". If you do not use expo when working with react-native, the following method will help you.
```js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
env: {
development: {
plugins: [['@babel/plugin-transform-react-jsx', {
runtime: 'automatic',
development: process.env.NODE_ENV === 'development',
importSource: '@welldone-software/why-did-you-render',
}]],
},
},
}
```
#### Expo managed
You can pass params to `@babel/preset-react` through `babel-preset-expo`
```js
// babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: [
[
"babel-preset-expo",
{
jsxImportSource: "@welldone-software/why-did-you-render",
},
],
],
};
};
```
> Notice: Create React App (CRA) ^4 **uses the `automatic` JSX transformation.**
> [See the following comment on how to do this step with CRA](https://github.com/welldone-software/why-did-you-render/issues/154#issuecomment-773905769)
Create a `wdyr.js` file and import it as **the very first import** in your application.
`wdyr.js`:
```jsx
import React from 'react';
if (process.env.NODE_ENV === 'development') {
const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React, {
trackAllPureComponents: true,
});
}
```
> [!CAUTION]
> The library should *NEVER* be used in production because:
> - It significantly slows down React
> - It monkey patches React and can result in unexpected behavior
In [Typescript](https://github.com/welldone-software/why-did-you-render/issues/161), call the file wdyr.ts and add the following line to the top of the file to import the package's types:
```tsx
///
```
Import `wdyr` as the first import (even before `react-hot-loader` if you use it):
`index.js`:
```jsx
import './wdyr'; // <--- first import
import 'react-hot-loader';
import React from 'react';
import ReactDOM from 'react-dom';
// ...
import {App} from './app';
// ...
ReactDOM.render(, document.getElementById('root'));
```
If you use `trackAllPureComponents`, all pure components ([React.PureComponent](https://reactjs.org/docs/react-api.html#reactpurecomponent) or [React.memo](https://reactjs.org/docs/react-api.html#reactmemo)) will be tracked.
Otherwise, add `whyDidYouRender = true` to ad-hoc components to track them. (f.e `Component.whyDidYouRender = true`)
More information about what is tracked can be found in [Tracking Components](#tracking-components).
Can't see any WDYR logs? Check out the [troubleshooting section](#troubleshooting) or search in the [issues](https://github.com/welldone-software/why-did-you-render/issues).
## Custom Hooks
Also, tracking custom hooks is possible by using `trackExtraHooks`. For example if you want to track `useSelector` from React Redux:
`wdyr.js`:
```jsx
import React from 'react';
// For react-native you might want to use
// the __DEV__ flag instead of process.env.NODE_ENV === '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']
]
});
}
```
> 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](https://github.com/welldone-software/why-did-you-render/issues/85).
## Read More
* [Why Did You Render Mr. Big Pure React Component???](http://bit.ly/wdyr1)
* [**Common fixing scenarios** this library can help with](http://bit.ly/wdyr02)
* [**React Hooks** - Understand and fix hooks issues](http://bit.ly/wdyr3)
* [Why Did You Render v4 Released!](https://medium.com/welldone-software/why-did-you-render-v4-released-48e0f0b99d4c) - TypeScript support, Custom hooks tracking (like React-Redux’s useSelector), Tracking of all pure components.
## Integration With Other Libraries
* [Next.js example](https://github.com/zeit/next.js/tree/canary/examples/with-why-did-you-render)
* [React-Redux With Hooks](https://medium.com/welldone-software/why-did-you-render-v4-released-48e0f0b99d4c)
* [Mobx is currently not supported](https://github.com/welldone-software/why-did-you-render/issues/162)
* [React-Native flipper plugin made by @allen-hsu](https://github.com/allen-hsu/wdyr-flipper#wdry-flipper-reporter)
## Sandbox
You can test the library in [the official sandbox](http://bit.ly/wdyr-sb).
And another [official sandbox with hooks tracking](https://codesandbox.io/s/why-did-you-render-sandbox-with-hooks-pyi14)
## Tracking Components
You can track all pure components ([React.PureComponent](https://reactjs.org/docs/react-api.html#reactpurecomponent) or [React.memo](https://reactjs.org/docs/react-api.html#reactmemo)) using the `trackAllPureComponents: true` option.
You can also manually track any component you want by setting `whyDidYouRender` on them like this:
```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
)
}
}
```
Or for functional components:
```js
const BigListPureComponent = props => (
//some heavy component you want to ensure doesn't happen if its not necessary
)
BigListPureComponent.whyDidYouRender = true
```
You can also pass an object to specify more advanced tracking settings:
```js
EnhancedMenu.whyDidYouRender = {
logOnDifferentValues: true,
customName: 'Menu'
}
```
- `logOnDifferentValues`:
Normally, only re-renders that are caused by equal values in props / state trigger notifications:
```js
render(