welldone-software / why-did-you-render

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://www.npmjs.com/package/@welldone-software/why-did-you-render
MIT License
11.24k stars 201 forks source link

trackExtraHooks cannot set property of #<Object> which has only a getter #85

Open mwskwong opened 4 years ago

mwskwong commented 4 years ago

By specifying trackExtraHooks, the following error is thrown. NOTE: The error is only thrown when running in local machine, NOT in codesandbox.

Reproduction link: Edit why-did-you-render-test

whyDidYouRender.js:167 Uncaught TypeError: Cannot set property useSelector of #<Object> which has only a getter
    at whyDidYouRender.js:167
    at Array.forEach (<anonymous>)
    at zn (whyDidYouRender.js:150)
    at Module../src/index.js (index.js:9)
    at __webpack_require__ (bootstrap:785)
    at fn (bootstrap:150)
    at Object.1 (styles.css?f684:43)
    at __webpack_require__ (bootstrap:785)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1
(anonymous) @ whyDidYouRender.js:167
zn @ whyDidYouRender.js:150
./src/index.js @ index.js:9
__webpack_require__ @ bootstrap:785
fn @ bootstrap:150
1 @ styles.css?f684:43
__webpack_require__ @ bootstrap:785
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
manifest.json:1 Manifest: Line: 1, column: 1, Syntax error.
vzaidman commented 3 years ago

@nikitaNaredi please use ``` for code blocks so it will be more readable. for example:

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"]],
  });
}
vzaidman commented 3 years ago
  1. install craco: https://github.com/gsoft-inc/craco
  2. what we need to do is to ensure anybody who imports react-redux imports it as react-redux/lib because it's exports are of the cjs type, we can manipulate these exports. I've updated the bottom part of https://github.com/welldone-software/why-did-you-render/issues/154#issuecomment-773905769 to show how to add react-redux alias.
nikitaNaredi commented 3 years ago

Thanks @vzaidman but still no luck, I have installed and created a craco.config.js. And added the code of https://github.com/welldone-software/why-did-you-render/issues/154#issuecomment-773905769 I don't know what else it missing. Craco version: "@craco/craco": "^6.1.2",

And craco.congif.js

module.exports = {
  babel: {
    loaderOptions: (babelLoaderOptions) => {
      const origBabelPresetCRAIndex = babelLoaderOptions.presets.findIndex(
        (preset) => {
          return preset[0].includes("babel-preset-react-app");
        }
      );

      const origBabelPresetCRA =
        babelLoaderOptions.presets[origBabelPresetCRAIndex];

      babelLoaderOptions.presets[
        origBabelPresetCRAIndex
      ] = function overridenPresetCRA(api, opts, env) {
        const babelPresetCRAResult = require(origBabelPresetCRA[0])(
          api,
          origBabelPresetCRA[1],
          env
        );

        babelPresetCRAResult.presets.forEach((preset) => {
          // detect @babel/preset-react with {development: true, runtime: 'automatic'}
          const isReactPreset =
            preset &&
            preset[1] &&
            preset[1].runtime === "automatic" &&
            preset[1].development === true;
          if (isReactPreset) {
            preset[1].importSource = "@welldone-software/why-did-you-render";
          }
        });

        return babelPresetCRAResult;
      };

      return babelLoaderOptions;
    },
  },
  // if you want to track react-redux selectors
  webpack: {
    alias: {
      "react-redux":
        process.env.NODE_ENV === "development"
          ? "react-redux/lib"
          : "react-redux",
    },
  },
};
mkamalkayani commented 3 years ago

I got this error when I mistakenly used default export for a named export component.

const useControlledState = require('module-smoove/src/smoove/helpers/useControlledState');

instead of

const { useControlledState } = require('module-smoove/src/smoove/helpers/useControlledState');

tomekzaw commented 1 year ago

Hey all, I got a similar error when trying to use why-did-you-render 7.0.1 with React Native 0.71.6 and react-redux 8.0.5:

TypeError: Cannot assign to property 'useSelector' which has only a getter, js engine: hermes

Fortunately, it's possible to fix it with the following two patches:

@welldone-software+why-did-you-render+7.0.1.patch

diff --git a/node_modules/@welldone-software/why-did-you-render/jsx-dev-runtime.js b/node_modules/@welldone-software/why-did-you-render/jsx-dev-runtime.js
index fabd293..0d6a323 100644
--- a/node_modules/@welldone-software/why-did-you-render/jsx-dev-runtime.js
+++ b/node_modules/@welldone-software/why-did-you-render/jsx-dev-runtime.js
@@ -5,8 +5,9 @@ var WDYR = require('@welldone-software/why-did-you-render')
 var origJsxDev = jsxDevRuntime.jsxDEV
 var wdyrStore = WDYR.wdyrStore

-module.exports = jsxDevRuntime
-module.exports.jsxDEV = function jsxDEV(){
+module.exports = {
+   ...jsxDevRuntime,
+   jsxDEV: function jsxDEV(){
   var args = Array.prototype.slice.call(arguments)

   if(wdyrStore.React && wdyrStore.React.isWDYR){
@@ -35,4 +36,4 @@ module.exports.jsxDEV = function jsxDEV(){
   }

   return origJsxDev.apply(null, args)
-}
+}}

react-redux+8.0.5.patch

diff --git a/node_modules/react-redux/lib/exports.js b/node_modules/react-redux/lib/exports.js
index 4235b88..a2065c5 100644
--- a/node_modules/react-redux/lib/exports.js
+++ b/node_modules/react-redux/lib/exports.js
@@ -49,6 +49,9 @@ Object.defineProperty(exports, "useSelector", {
   enumerable: true,
   get: function () {
     return _useSelector.useSelector;
+  },
+  set: function (value) {
+    _useSelector.useSelector = value;
   }
 });
 Object.defineProperty(exports, "createSelectorHook", {
diff --git a/node_modules/react-redux/lib/index.js b/node_modules/react-redux/lib/index.js
index 07dcece..e8f176f 100644
--- a/node_modules/react-redux/lib/index.js
+++ b/node_modules/react-redux/lib/index.js
@@ -33,6 +33,9 @@ Object.keys(_exports).forEach(function (key) {
     enumerable: true,
     get: function () {
       return _exports[key];
+    },
+    set: function (value) {
+      _exports[key] = value;
     }
   });
 });

Here are my files:

wdyr.js

import React from 'react';

if (__DEV__) {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  const ReactRedux = require('react-redux');
  whyDidYouRender(React, {
    trackAllPureComponents: true,
    logOnDifferentValues: true,
    trackExtraHooks: [[ReactRedux, 'useSelector']],
  });
}

babel.plugin.js

module.exports = {
  presets: [
    [
      'module:metro-react-native-babel-preset',
      { useTransformReactJSXExperimental: true },
    ],
    [
      '@babel/preset-react',
      {
        importSource: '@welldone-software/why-did-you-render',
        runtime: 'automatic',
        development: true,
      },
    ],
  ],
  plugins: ['react-native-reanimated/plugin'],
};
chmiiller commented 1 year ago

I have the exactly same as @tomekzaw , is there a solution for it?

tomekzaw commented 1 year ago

Hey @chmiiller, have you tried the solution from my comment? It worked for me back then. You need to modify 2 files:

chmiiller commented 1 year ago

yes, I've tried that and it works @tomekzaw , thanks for that! I'm just saying that maybe this patch on jsx-dev-runtime should be merged in the source code of why-did-you-render.

Furqan558 commented 1 year ago

Hey @chmiiller, have you tried the solution from my comment? It worked for me back then. You need to modify 2 files:

  • node_modules/@welldone-software/why-did-you-render/jsx-dev-runtime.js
  • node_modules/react-redux/lib/exports.js

exports.js doesn't exist @tomekzaw

Hypnosphi commented 11 months ago

The UMD build was removed in react-redux@9.0 so the workaround doesn't work anymore

https://redux.js.org/usage/migrations/migrating-rtk-2#dropping-umd-builds

TomerAtarScopio commented 6 months ago

I had stumbled here getting the same message but without using any hooks, seems that my configuration was wrong (as our project had been using an old react version prior to the upgrade)

- import * as React from 'react';
+ import React from 'react';

if (process.env.NODE_ENV === 'development') {
    const whyDidYouRender = require('@welldone-software/why-did-you-render');
    whyDidYouRender(React, {
        trackAllPureComponents: false,
    });
}
chmiiller commented 6 months ago

was that enough for you to fix it on react-redux@9.x @TomerAtarScopio ?