[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-3433":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":35,"readmeContent":36,"aiSummary":37,"trendingCount":16,"starSnapshotCount":16,"syncStatus":38,"lastSyncTime":39,"discoverSource":40},3433,"why-did-you-render","welldone-software\u002Fwhy-did-you-render","welldone-software","why-did-you-render by Welldone Software monkey patches React to notify you about potentially avoidable re-renders. (Works with React Native as well.)","https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@welldone-software\u002Fwhy-did-you-render",null,"JavaScript",12488,227,37,31,0,1,18,69.37,"MIT License",false,"master",true,[25,26,27,28,29,30,31,32,33,34],"component","hooks-tracking","performance","pure","purecomponent","react","react-native","render","tool","update","2026-06-12 04:00:17","\u003Cp align=\"center\">\n  \u003Cimg src=\"images\u002FWDYR-logo.jpg\" width=\"300px\" \u002F>\n\u003C\u002Fp>\n\n# Why Did You Render\n\n[![npm version](https:\u002F\u002Fbadge.fury.io\u002Fjs\u002F%40welldone-software%2Fwhy-did-you-render.svg)](https:\u002F\u002Fbadge.fury.io\u002Fjs\u002F%40welldone-software%2Fwhy-did-you-render)\n[![Build Status](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Factions\u002Fworkflows\u002Fmain.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Factions\u002Fworkflows\u002Fmain.yml)\n[![license](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fl\u002F@welldone-software\u002Fwhy-did-you-render?style=flat)](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fblob\u002Fmaster\u002FLICENSE)\n[![@welldone-software\u002Fwhy-did-you-render](https:\u002F\u002Fsnyk.io\u002Fadvisor\u002Fnpm-package\u002F@welldone-software\u002Fwhy-did-you-render\u002Fbadge.svg)](https:\u002F\u002Fsnyk.io\u002Fadvisor\u002Fnpm-package\u002F@welldone-software\u002Fwhy-did-you-render)\n[![Coverage Status](https:\u002F\u002Fcoveralls.io\u002Frepos\u002Fgithub\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fbadge.svg?branch=add-e2e-tests-using-cypress)](https:\u002F\u002Fcoveralls.io\u002Fgithub\u002Fwelldone-software\u002Fwhy-did-you-render?branch=add-e2e-tests-using-cypress)\n\n`why-did-you-render` by [Welldone Software](https:\u002F\u002Fwelldone.software\u002F) monkey patches **`React`** to notify you about potentially avoidable re-renders. (Works with **`React Native`** as well.)\n\nFor example, if you pass `style={{width: '100%'}}` to a big memo component it would always re-render on every element creation:\n```jsx\n\u003CMemoBigList style={{width: '100%'}}\u002F>\n```\nIt can also help you to simply track when and why a certain component re-renders.\n\n> [!CAUTION]\n> The library was not tested with [React Compiler](https:\u002F\u002Freact.dev\u002Flearn\u002Freact-compiler) at all. I believe it's completely incompatible with it.\n\n> [!CAUTION]\n> 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:\u002F\u002Flegacy.reactjs.org\u002Fblog\u002F2018\u002F09\u002F10\u002Fintroducing-the-react-profiler.html) to measure the effects of any changes.\n\n> [!NOTE]\nI'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:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fdiscussions\u002F309)!\n\n## Setup\nThe latest version of the library was tested [(unit tests and E2E)]((https:\u002F\u002Ftravis-ci.com\u002Fwelldone-software\u002Fwhy-did-you-render.svg?branch=master)) with **`React@19`** only.\n* [For `React 18`, please see the readme for version @^8](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Ftree\u002Fversion-8).\n* [For `React 17` and `React 16`, please see the readme for version @^7](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Ftree\u002Fversion-7).\n\n```\nnpm install @welldone-software\u002Fwhy-did-you-render --save-dev\n```\nor\n```\nyarn add @welldone-software\u002Fwhy-did-you-render -D\n```\nSet the library to be the React's importSource and make sure `preset-react` is in `development` mode.\n\nThis is because `React 19` requires using the `automatic` [JSX transformation](https:\u002F\u002Flegacy.reactjs.org\u002Fblog\u002F2020\u002F09\u002F22\u002Fintroducing-the-new-jsx-transform.html). \n```js\n['@babel\u002Fpreset-react', {\n  runtime: 'automatic',\n  development: process.env.NODE_ENV === 'development',\n  importSource: '@welldone-software\u002Fwhy-did-you-render',\n}]\n```\n\n### React Native\n\n#### Bare workflow\n\nAdd 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.\n\n```js\nmodule.exports = {\n  presets: ['module:metro-react-native-babel-preset'],\n\n  env: {\n    development: {\n      plugins: [['@babel\u002Fplugin-transform-react-jsx', {\n        runtime: 'automatic',\n        development: process.env.NODE_ENV === 'development',\n        importSource: '@welldone-software\u002Fwhy-did-you-render',\n      }]],\n    },\n  },\n}\n```\n\n#### Expo managed\n\nYou can pass params to `@babel\u002Fpreset-react` through `babel-preset-expo`\n\n```js\n\u002F\u002F babel.config.js\nmodule.exports = function (api) {\n  api.cache(true);\n  return {\n    presets: [\n      [\n        \"babel-preset-expo\",\n        {\n          jsxImportSource: \"@welldone-software\u002Fwhy-did-you-render\",\n        },\n      ],\n    ],\n  };\n};\n```\n\n> Notice: Create React App (CRA) ^4 **uses the `automatic` JSX transformation.**\n> [See the following comment on how to do this step with CRA](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fissues\u002F154#issuecomment-773905769)\n\nCreate a `wdyr.js` file and import it as **the very first import** in your application.\n\n`wdyr.js`:\n```jsx\nimport React from 'react';\n\nif (process.env.NODE_ENV === 'development') {\n  const whyDidYouRender = require('@welldone-software\u002Fwhy-did-you-render');\n  whyDidYouRender(React, {\n    trackAllPureComponents: true,\n  });\n}\n```\n\n> [!CAUTION]\n> The library should *NEVER* be used in production because:\n> - It significantly slows down React\n> - It monkey patches React and can result in unexpected behavior\n\nIn [Typescript](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fissues\u002F161), call the file wdyr.ts and add the following line to the top of the file to import the package's types:\n```tsx\n\u002F\u002F\u002F \u003Creference types=\"@welldone-software\u002Fwhy-did-you-render\" \u002F>\n```\n\nImport `wdyr` as the first import (even before `react-hot-loader` if you use it):\n\n`index.js`:\n\n```jsx\nimport '.\u002Fwdyr'; \u002F\u002F \u003C--- first import\n\nimport 'react-hot-loader';\n\nimport React from 'react';\nimport ReactDOM from 'react-dom';\n\u002F\u002F ...\nimport {App} from '.\u002Fapp';\n\u002F\u002F ...\nReactDOM.render(\u003CApp\u002F>, document.getElementById('root'));\n```\n\nIf you use `trackAllPureComponents`, all pure components ([React.PureComponent](https:\u002F\u002Freactjs.org\u002Fdocs\u002Freact-api.html#reactpurecomponent) or [React.memo](https:\u002F\u002Freactjs.org\u002Fdocs\u002Freact-api.html#reactmemo)) will be tracked.\n\nOtherwise, add `whyDidYouRender = true` to ad-hoc components to track them. (f.e `Component.whyDidYouRender = true`)\n\nMore information about what is tracked can be found in [Tracking Components](#tracking-components).\n\nCan't see any WDYR logs? Check out the [troubleshooting section](#troubleshooting) or search in the [issues](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fissues).\n\n## Custom Hooks\n\nAlso, tracking custom hooks is possible by using `trackExtraHooks`. For example if you want to track `useSelector` from React Redux:\n\n`wdyr.js`:\n```jsx\nimport React from 'react';\n\n\u002F\u002F For react-native you might want to use \n\u002F\u002F the __DEV__ flag instead of process.env.NODE_ENV === 'development'\nif (process.env.NODE_ENV === 'development') {\n  const whyDidYouRender = require('@welldone-software\u002Fwhy-did-you-render');\n  const ReactRedux = require('react-redux');\n  whyDidYouRender(React, {\n    trackAllPureComponents: true,\n    trackExtraHooks: [\n      [ReactRedux, 'useSelector']\n    ]\n  });\n}\n```\n\n> 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:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fissues\u002F85).\n\n## Read More\n* [Why Did You Render Mr. Big Pure React Component???](http:\u002F\u002Fbit.ly\u002Fwdyr1)\n* [**Common fixing scenarios** this library can help with](http:\u002F\u002Fbit.ly\u002Fwdyr02)\n* [**React Hooks** - Understand and fix hooks issues](http:\u002F\u002Fbit.ly\u002Fwdyr3)\n* [Why Did You Render v4 Released!](https:\u002F\u002Fmedium.com\u002Fwelldone-software\u002Fwhy-did-you-render-v4-released-48e0f0b99d4c) - TypeScript support, Custom hooks tracking (like React-Redux’s useSelector), Tracking of all pure components.\n\n## Integration With Other Libraries\n* [Next.js example](https:\u002F\u002Fgithub.com\u002Fzeit\u002Fnext.js\u002Ftree\u002Fcanary\u002Fexamples\u002Fwith-why-did-you-render)\n* [React-Redux With Hooks](https:\u002F\u002Fmedium.com\u002Fwelldone-software\u002Fwhy-did-you-render-v4-released-48e0f0b99d4c)\n* [Mobx is currently not supported](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fissues\u002F162)\n* [React-Native flipper plugin made by @allen-hsu](https:\u002F\u002Fgithub.com\u002Fallen-hsu\u002Fwdyr-flipper#wdry-flipper-reporter)\n\n## Sandbox\nYou can test the library in [the official sandbox](http:\u002F\u002Fbit.ly\u002Fwdyr-sb).\n\nAnd another [official sandbox with hooks tracking](https:\u002F\u002Fcodesandbox.io\u002Fs\u002Fwhy-did-you-render-sandbox-with-hooks-pyi14)\n\n## Tracking Components\nYou can track all pure components ([React.PureComponent](https:\u002F\u002Freactjs.org\u002Fdocs\u002Freact-api.html#reactpurecomponent) or [React.memo](https:\u002F\u002Freactjs.org\u002Fdocs\u002Freact-api.html#reactmemo)) using the `trackAllPureComponents: true` option.\n\nYou can also manually track any component you want by setting `whyDidYouRender` on them like this:\n```js\nclass BigList extends React.Component {\n  static whyDidYouRender = true\n  render(){\n    return (\n      \u002F\u002Fsome heavy render you want to ensure doesn't happen if its not necessary\n    )\n  }\n}\n```\n\nOr for functional components:\n\n```js\nconst BigListPureComponent = props => (\n  \u003Cdiv>\n    \u002F\u002Fsome heavy component you want to ensure doesn't happen if its not necessary\n  \u003C\u002Fdiv>\n)\nBigListPureComponent.whyDidYouRender = true\n```\n\nYou can also pass an object to specify more advanced tracking settings:\n\n```js\nEnhancedMenu.whyDidYouRender = {\n  logOnDifferentValues: true,\n  customName: 'Menu'\n}\n```\n\n- `logOnDifferentValues`:\n\n  Normally, only re-renders that are caused by equal values in props \u002F state trigger notifications:\n  ```js\n  render(\u003CMenu a={1}\u002F>)\n  render(\u003CMenu a={1}\u002F>)\n  ```\n  This option will trigger notifications even if they occurred because of different props \u002F state (Thus, because of \"legit\" re-renders):\n  ```js\n  render(\u003CMenu a={1}\u002F>)\n  render(\u003CMenu a={2}\u002F>)\n  ```\n\n- `customName`:\n\n  Sometimes the name of the component can be missing or very inconvenient. For example:\n\n  ```js\n  withPropsOnChange(withPropsOnChange(withStateHandlers(withPropsOnChange(withState(withPropsOnChange(lifecycle(withPropsOnChange(withPropsOnChange(onlyUpdateForKeys(LoadNamespace(Connect(withState(withState(withPropsOnChange(lifecycle(withPropsOnChange(withHandlers(withHandlers(withHandlers(withHandlers(Connect(lifecycle(Menu)))))))))))))))))))))))\n  ```\n\n## Options\nOptionally you can pass in `options` as the second parameter. The following options are available:\n- `include: [RegExp, ...]` (`null` by default)\n- `exclude: [RegExp, ...]` (`null` by default)\n- `trackAllPureComponents: false`\n- `trackHooks: true`\n- `trackExtraHooks: []`\n- `logOwnerReasons: true`\n- `logOnDifferentValues: false`\n- `hotReloadBufferMs: 500`\n- `onlyLogs: false`\n- `collapseGroups: false`\n- `titleColor`\n- `diffNameColor`\n- `diffPathColor`\n- `textBackgroundColor`\n- `notifier: ({Component, displayName, hookName, prevProps, prevState, prevHookResult, nextProps, nextState, nextHookResult, reason, options, ownerDataMap}) => void`\n- `getAdditionalOwnerData: (element) => {...}`\n\n#### include \u002F exclude\n##### (default: `null`)\n\nYou can include or exclude tracking of components by their displayName using the `include` and `exclude` options.\n\nFor example, the following code is used to [track all redundant re-renders that are caused by older React-Redux](http:\u002F\u002Fbit.ly\u002Fwdyr04):\n```js\nwhyDidYouRender(React, { include: [\u002F^ConnectFunction\u002F] });\n```\n> *Notice: **exclude** takes priority over both `include` and manually set `whyDidYouRender = `*\n\n#### trackAllPureComponents\n##### (default: `false`)\n\nYou can track all pure components (both `React.memo` and `React.PureComponent` components)\n\n> *Notice: You can exclude the tracking of any specific component with `whyDidYouRender = false`*\n\n#### trackHooks\n##### (default: `true`)\n\nYou can turn off tracking of hooks changes.\n\n[Understand and fix hook issues](http:\u002F\u002Fbit.ly\u002Fwdyr3).\n\n#### trackExtraHooks\n##### (default: `[]`)\n\nTrack custom hooks:\n\n```js\nwhyDidYouRender(React, {\n  trackExtraHooks: [\n    \u002F\u002F notice that 'useSelector' is a named export\n    [ReactRedux, 'useSelector'],\n  ]\n});\n```\n\n> This feature is rewriting exports of imported files. There is currently a problem with that approach in webpack. A workaround is available here: [#85 - trackExtraHooks cannot set property](https:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fissues\u002F85)\n\n#### logOwnerReasons\n##### (default: `true`)\n\nOne way of fixing re-render issues is preventing the component's owner from re-rendering.\n\nThis option is `true` by default and it lets you view the reasons why an owner component re-renders.\n\n![demo](images\u002FlogOwnerReasons.png)\n\n#### logOnDifferentValues\n##### (default: `false`)\n\nNormally, you only want logs about component re-renders when they could have been avoided.\n\nWith this option, it is possible to track all re-renders.\n\nFor example:\n```js\nrender(\u003CBigListPureComponent a={1}\u002F>)\nrender(\u003CBigListPureComponent a={2}\u002F>)\n\u002F\u002F will only log if you use {logOnDifferentValues: true}\n```\n\n#### hotReloadBufferMs\n##### (default: `500`)\n\nTime in milliseconds to ignore updates after a hot reload is detected.\n\nWhen a hot reload is detected, we ignore all updates for `hotReloadBufferMs` to not spam the console.\n\n#### onlyLogs\n##### (default: `false`)\n\nIf you don't want to use `console.group` to group logs you can print them as simple logs.\n\n#### collapseGroups\n##### (default: `false`)\n\nGrouped logs can be collapsed.\n\n#### titleColor \u002F diffNameColor \u002F diffPathColor \u002F textBackgroundColor\n##### (default titleColor: `'#058'`)\n##### (default diffNameColor: `'blue'`)\n##### (default diffPathColor: `'red'`)\n##### (default textBackgroundColor: `'white`)\n\nControls the colors used in the console notifications\n\n#### notifier\n##### (default: defaultNotifier that is exposed from the library)\n\nYou can create a custom notifier if the default one does not suite your needs.\n\n#### getAdditionalOwnerData\n##### (default: `undefined`)\nYou can provide a function that harvests additional data from the original react element. The object returned from this function will be added to the ownerDataMap which can be accessed later within your notifier function override.\n\n## Troubleshooting\n\n### No tracking\n* If you are in production, WDYR is probably disabled.\n* Maybe no component is tracked\n    * Check out [Tracking Components](#tracking-components) once again.\n* If you only track pure components using `trackAllPureComponents: true` then you would only track either ([React.PureComponent](https:\u002F\u002Freactjs.org\u002Fdocs\u002Freact-api.html#reactpurecomponent) or [React.memo](https:\u002F\u002Freactjs.org\u002Fdocs\u002Freact-api.html#reactmemo)), maybe none of your components are pure so none of them will get tracked.\n* Maybe you have no issues\n    * Try causing an issue by temporary rendering the whole app twice in it's entry point:\n\n        `index.js`:\n        ```jsx\n        const HotApp = hot(App);\n        HotApp.whyDidYouRender = true;\n        ReactDOM.render(\u003CHotApp\u002F>, document.getElementById('root'));\n        ReactDOM.render(\u003CHotApp\u002F>, document.getElementById('root'));\n        ```\n\n### Custom Hooks tracking (like useSelector)\nThere'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:\u002F\u002Fgithub.com\u002Fwelldone-software\u002Fwhy-did-you-render\u002Fissues\u002F85).\n\n### React-Redux `connect` HOC is spamming the console\nSince `connect` hoists statics, if you add WDYR to the inner component, it is also added to the HOC component where complex hooks are running.\n\nTo fix this, add the `whyDidYouRender = true` static to a component after the connect:\n```js\n  const SimpleComponent = ({a}) => \u003Cdiv data-testid=\"foo\">{a.b}\u003C\u002Fdiv>)\n  \u002F\u002F not before the connect:\n  \u002F\u002F SimpleComponent.whyDidYouRender = true\n  const ConnectedSimpleComponent = connect(\n    state => ({a: state.a})\n  )(SimpleComponent)\n  \u002F\u002F after the connect:\n  SimpleComponent.whyDidYouRender = true\n```\n\n### Sourcemaps\nTo see the library's sourcemaps use the [source-map-loader](https:\u002F\u002Fwebpack.js.org\u002Floaders\u002Fsource-map-loader\u002F).\n\n## Credit\n\nInspired by the following previous work:\n\n* github.com\u002Fmaicki\u002Fwhy-did-you-update (no longer public) which I had the chance to maintain for some time.\n* https:\u002F\u002Fgithub.com\u002Fgarbles\u002Fwhy-did-you-update where [A deep dive into React perf debugging](https:\u002F\u002Fbenchling.engineering\u002Fa-deep-dive-into-react-perf-debugging-fd2063f5a667\u002F) is credited for the idea.\n\n## License\n\nThis library is [MIT licensed](.\u002FLICENSE).\n\n[🔼Back to top!](#Why-Did-You-Render)\n","`why-did-you-render` 是一个由 Welldone Software 开发的工具，通过猴子补丁技术监控 React 组件的重新渲染情况，并通知开发者哪些重新渲染可能是可以避免的，同时支持 React Native。其核心功能包括追踪组件的更新原因、识别不必要的重新渲染，从而帮助开发者优化性能。该工具特别适合在开发过程中用于检测和改进大型或复杂组件的渲染效率问题。使用此工具可以帮助开发者更好地理解组件的行为，特别是在应用性能优化阶段。",2,"2026-06-11 02:54:23","top_language"]