GithubHelp home page GithubHelp logo

zhangaz1 / why-did-you-render Goto Github PK

View Code? Open in Web Editor NEW

This project forked from welldone-software/why-did-you-render

0.0 1.0 0.0 2.92 MB

why-did-you-render monkey patches React to notify you about avoidable re-renders.

Home Page: https://www.npmjs.com/package/@welldone-software/why-did-you-render

License: MIT License

JavaScript 99.18% TypeScript 0.82%

why-did-you-render's Introduction

Why Did You Render

npm version

why-did-you-render monkey patches React to notify you about avoidable re-renders. (Works with React Native as well.)

For example, when you pass style={{width: '100%'}} to a big pure component and make it always re-render:

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 this library can help to eliminate can be found >> HERE <<.
  • Part 3 - React Hooks - Understand and fix hooks issues >> HERE <<.
  • Part 4 - React-Redux - Understand and fix react-redux issues >> HERE <<.

Sandbox

You can test the library in the official sandbox >> HERE <<.

Setup

The required React version for the library is 16.12 but it is expected to work with older versions as well.

For versions before 16.8 turn off hooks support by using trackHooks: false in whyDidYouRender's init options.*

npm install @welldone-software/why-did-you-render --save

or

yarn add @welldone-software/why-did-you-render

Installation

Execute whyDidYouRender with React as it's first argument before any React element is created.

import React from 'react';

if (process.env.NODE_ENV !== 'production') {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React);
}

Usage

Mark any component you want to be notified about their "redundant" re-renders with whyDidYouRender like this:

class BigListPureComponent extends React.PureComponent {
  static whyDidYouRender = true
  render(){
    return (
      //some heavy render you want to ensure doesn't happen if its not neceserry
    )
  }
}

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: 'Menu'
}
  • 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 = 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:

    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 the second parameter. The following options are available:

  • include: [RegExp, ...] (null by default)
  • exclude: [RegExp, ...] (null by default)
  • trackHooks: true
  • trackExtraHooks: []
  • logOnDifferentValues: false
  • hotReloadBufferMs: 500
  • onlyLogs: false
  • collapseGroups: false
  • titleColor
  • diffNameColor
  • diffPathColor
  • 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.

For example, the following code is used to track all redundant re-renders that are caused by React-Redux:

whyDidYouRender(React, { include: [/^ConnectFunction/] });

trackHooks

You can turn off tracking of hooks changes.

Understand and fix hook issues >> HERE <<.

trackExtraHooks

Adding extra hooks to track for "redundant" results:

whyDidYouRender(React, {trackExtraHooks: [
  [Redux, 'useSelector']
]});

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}/>)
// this will only cause whyDidYouRender notifications for {logOnDifferentValues: true}

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.

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:

titleColor / diffNameColor / diffPathColor

Controls the colors used in the console notifications

notifier

You can create a custom notifier if the default one does not suite your needs.

Troubleshooting

Class constructors must be invoked with 'new'.

If you are building for latest browsers (or using es6 classes without building) you don't transpile the "class" keyword.

This causes an error because the library uses transpiled classes, and transpiled classes currently can't extend native classes.

To fix this, 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);
}

React-Redux connect HOC is spamming the console

Since connect hoists statics, if you add WDYR to the inner component, it is also added to the HOC component where complex hooks are running.

To fix this, add the whyDidYouRender = true static to a component after the connect:

  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

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.

why-did-you-render's People

Contributors

genhain avatar jared-hexagon avatar joelbrenstrum avatar leroydev avatar mostafah avatar noramens avatar vzaidman avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.