What is @welldone-software/why-did-you-render?
@welldone-software/why-did-you-render is a tool for debugging unnecessary re-renders in React applications. It helps developers identify and fix performance issues by logging information about why a component re-rendered.
What are @welldone-software/why-did-you-render's main functionalities?
Basic Setup
This code sets up the @welldone-software/why-did-you-render package to track all pure components in a React application. It helps in identifying unnecessary re-renders by logging detailed information.
const React = require('react');
const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React, {
trackAllPureComponents: true,
});
Tracking Specific Components
This code demonstrates how to track a specific component for unnecessary re-renders. By setting the static property `whyDidYouRender` to true, the package will log information whenever `MyComponent` re-renders.
import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';
whyDidYouRender(React);
class MyComponent extends React.Component {
static whyDidYouRender = true;
render() {
return <div>{this.props.text}</div>;
}
}
Customizing Log Output
This code customizes the log output by including and excluding specific components. It also enables logging when prop values change. This helps in fine-tuning the debugging process to focus on specific parts of the application.
import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';
whyDidYouRender(React, {
logOnDifferentValues: true,
include: [/^MyComponent$/],
exclude: [/^SomeOtherComponent$/],
});
Other packages similar to @welldone-software/why-did-you-render
react-perf-devtool
react-perf-devtool is a performance monitoring tool for React applications. It provides a visual representation of component render times and helps identify performance bottlenecks. Unlike @welldone-software/why-did-you-render, which focuses on logging re-renders, react-perf-devtool offers a more visual approach to performance monitoring.
react-axe
react-axe is a tool for auditing React applications for accessibility issues. While it doesn't focus on performance like @welldone-software/why-did-you-render, it helps developers ensure their applications are accessible to all users. It provides real-time feedback on accessibility issues directly in the browser's developer tools.
react-devtools
react-devtools is an official tool from Facebook for inspecting the React component tree. It allows developers to view the state and props of components, as well as track component updates. While it doesn't specifically target unnecessary re-renders, it provides a comprehensive set of tools for debugging React applications.
Why Did You Render
![npm version](https://badge.fury.io/js/%40welldone-software%2Fwhy-did-you-render.svg)
why-did-you-render
monkey patches React
to notify you about avoidable re-renders.
For example, when you pass style={{width: '100%'}}
to a big pure component and make it always re-render:
![](https://raw.githubusercontent.com/welldone-software/why-did-you-render/master/demo-image.png)
It can also help you to simply track when and why a certain component re-renders.
Read More
You can read more about the library >> HERE <<.
Part 2 - Common Fixing Scenarios
Common fixing scenarios this library can help to eliminate can be found >> HERE <<.
Part 3 - Hooks
Understand and fix hook issues >> HERE <<.
Sandbox
You can test the library in the official sandbox >> HERE <<.
Setup
npm install @welldone-software/why-did-you-render --save
or
yarn add @welldone-software/why-did-you-render
Usage
Execute whyDidYouRender
with React
as it's first argument.
import React from 'react';
if (process.env.NODE_ENV !== 'production') {
const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React);
}
If you are building for latest browsers and don't transpile the "class" keyword use the "no-classes-transpile" dist:
import React from 'react';
if (process.env.NODE_ENV !== 'production') {
const whyDidYouRender = require('@welldone-software/why-did-you-render/dist/no-classes-transpile/umd/whyDidYouRender.min.js');
whyDidYouRender(React);
}
Not doing so will result in a bug
where a transpiled class tries to extend a native class:
Class constructors must be invoked with 'new'
.
Then mark all the components you want to be notified about their re-renders with whyDidYouRender
like so:
class BigListPureComponent extends React.PureComponent {
static whyDidYouRender = true
render(){
return (
)
}
}
Or like this:
const BigListPureComponent = props => (
<div>
//some heavy component you want to ensure doesn't happen if its not neceserry
</div>
)
BigListPureComponent.whyDidYouRender = true
You can also pass an object to specify more advanced settings:
EnhancedMenu.whyDidYouRender = {
logOnDifferentValues: true,
customName: 'EnhancedMenu'
}
-
logOnDifferentValues
:
Normally only re-renders that are caused by equal values in props / state trigger notifications:
render(<Menu a={1}/>)
render(<Menu a={1}/>)
This option will trigger notifications even if they occurred because of different props / state (Thus, because of "legit" re-renders):
render(<Menu a={1}/>)
render(<Menu a={2}/>)
-
customName
:
Sometimes the name of the component can be very inconvenient. For example:
const EnhancedMenu = Connect(withPropsOnChange(withPropsOnChange(withStateHandlers(withPropsOnChange(withState(withPropsOnChange(lifecycle(withPropsOnChange(withPropsOnChange(onlyUpdateForKeys(LoadNamespace(Connect(withState(withState(withPropsOnChange(lifecycle(withPropsOnChange(withHandlers(withHandlers(withHandlers(withHandlers(Connect(lifecycle(Menu))))))))))))))))))))))))
will have the display name:
Connect(withPropsOnChange(withPropsOnChange(withStateHandlers(withPropsOnChange(withState(withPropsOnChange(lifecycle(withPropsOnChange(withPropsOnChange(onlyUpdateForKeys(LoadNamespace(Connect(withState(withState(withPropsOnChange(lifecycle(withPropsOnChange(withHandlers(withHandlers(withHandlers(withHandlers(Connect(lifecycle(Menu))))))))))))))))))))))))
To prevent polluting the console, and any other reason, you can change it using customName
.
Options
Optionally you can pass in options as a second parameter. The following options are available:
include: [RegExp, ...]
(null
by default)exclude: [RegExp, ...]
(null
by default)logOnDifferentValues: false
onlyLogs: false
collapseGroups: false
hotReloadBufferMs: 500
notifier: ({Component, displayName, prevProps, prevState, nextProps, nextState, reason, options}) => void
include / exclude
You can include or exclude tracking for re-renders for components
by their displayName with the include
and exclude
options.
Notice: exclude takes priority over both include
and whyDidYouRender
statics on components.
whyDidYouRender(React, { include: [/^pure/], exclude: [/^Connect/] });
logOnDifferentValues
Normally, you only want notifications about component re-renders when their props and state
are the same, because it means these re-renders could of been avoided. But you can also track
all re-renders, even on different state/props.
render(<BigListPureComponent a={1}/>)
render(<BigListPureComponent a={2}/>)
onlyLogs
If you don't want to use console.group
to group logs by component, you can print them as simple logs.
collapseGroups
Grouped logs can start collapsed:
hotReloadBufferMs
Time in milliseconds to ignore updates after a hot reload is detected.
We can't currently know exactly if a render was triggered by hot reload,
so instead, we ignore all updates for hotReloadBufferMs
(default: 500) after a hot reload.
notifier
A notifier can be provided if the default one does not suite your needs.
Credit
Inspired by the following previous work:
https://github.com/maicki/why-did-you-update which i had the chance to maintain for some time.
https://github.com/garbles/why-did-you-update where A deep dive into React perf debugging is credited for the idea.
License
This library is MIT licensed.