Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use with React Native & Expo? #235

Closed
duggster opened this issue Mar 19, 2022 · 31 comments · Fixed by #308
Closed

How to use with React Native & Expo? #235

duggster opened this issue Mar 19, 2022 · 31 comments · Fixed by #308
Labels
help wanted Extra attention is needed

Comments

@duggster
Copy link

I have used wdyr with my RN Expo app in the past, maybe a year ago, but now it is not showing anything in the logs. Any help would be greatly appreciated!

I created a new RN Expo app to use as a simplistic, reproducible example:
expo init wdyr-test
and choose option for blank project (managed workflow).

App.js

import './wdyr'; // <--- first import

import React, { useState } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';

export default function App() {

  const [count, setCount] = useState(0);

  const onPress = () => {
    console.log("Increment Pressed");
    setCount(prev => prev + 1);
  }

  console.log("App RENDER");

  return (
    <View style={styles.container}>

      <Text>{count}</Text>
      <Button title="Increment" onPress={onPress} />

      <Subcomponent style={{ height: 100, width: 100, borderRadius: 50, backgroundColor: "blue" }} />

    </View>
  );
}

const Subcomponent = React.memo(({ style }) => {

  console.log("Subcomponent RENDER");

  return (
    <View style={style} />
  )
});
Subcomponent.whyDidYouRender = true;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
    margin: 50
  },
});

wdyr.js

import React from 'react';

if (__DEV__) {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React, {
    trackAllPureComponents: true,
  });
}

package.json

{
  "name": "wdyr-test",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "expo": "~44.0.0",
    "expo-status-bar": "~1.2.0",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-native": "0.64.3",
    "react-native-web": "0.17.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@welldone-software/why-did-you-render": "^6.2.3"
  },
  "private": true
}

I don't know much (anything) about babel so just tried this for my bable.config.js but there was no change:

module.exports = function (api) {
  api.cache(true);

  const isDev = process.env.BABEL_ENV === "development";

  return {
    presets: [
      ['babel-preset-expo',
        {
          jsxRuntime: 'automatic',
          jsxImportSource: isDev ? '@welldone-software/why-did-you-render' : 'react'
        }
      ]
    ],
  };
};

All I get is this in the logs:

App RENDER
Subcomponent RENDER
Increment Pressed
App RENDER
Subcomponent RENDER
Increment Pressed
App RENDER
Subcomponent RENDER
@mariomurrent-softwaresolutions

Same here - any solution yet?

@zeevl
Copy link

zeevl commented Mar 29, 2022

I don't know about expo, but this was super helpful for me (and no, I'm not the author :))
https://yajanarao.medium.com/how-to-use-why-did-you-render-library-in-react-native-a95121978a75

@duggster
Copy link
Author

@zeevl Thanks for trying to help but It looks like this article basically just copies the installation and setup instructions from the main wdyr github page, though with less information. It also links to issue #58 here which doesn't have any resolution or workarounds mentioned in it. Let me know though if I missed anything specific that you were thinking might help.

@zeevl
Copy link

zeevl commented Mar 30, 2022

@duggster the main wdyr readme was has a lot of extra and misleading information that isn't applicable to get it working in RN. I got it working quickly by following the instructions in the linked post, but ymmv. Sounds like what you're running into may be specific to expo?

@duggster
Copy link
Author

If it's working for others on plain RN than chances are it is something with Expo involved (I've only ever used Expo, so I haven't tested other RN approaches). I also saw another issue #231 which is still open and I'm wondering if it has something to do with React 17.0.1 since the latest Expo also uses 17.0.1?

@vzaidman
Copy link
Collaborator

vzaidman commented Apr 2, 2022

If it's working for others on plain RN than chances are it is something with Expo involved (I've only ever used Expo, so I haven't tested other RN approaches). I also saw another issue #231 which is still open and I'm wondering if it has something to do with React 17.0.1 since the latest Expo also uses 17.0.1?

This issue has to do with CRA5 and not React 17.0.1.

I can't help with this one since I don't know anything about Expo.

@vzaidman vzaidman added the help wanted Extra attention is needed label Apr 2, 2022
@palicko
Copy link

palicko commented May 18, 2022

Had the same problem, WDYR stopped working in Expo 44.
As answers above suggested, it was probably because of React 17 and CRA.

All I had to do is to add another preset to my babel.config.js, like this:

presets: [
  'babel-preset-expo',
  [
    '@babel/preset-react',
    {
      importSource: '@welldone-software/why-did-you-render',
      runtime: 'automatic',
      development: process.env.NODE_ENV === 'development' || false,
    },
  ],
],

Edit: also make sure you have @babel/preset-react package installed.

@duggster
Copy link
Author

Hi @palicko I tried this and got the following error trying to run my expo app:
Error: Cannot find module '@babel/preset-react'

How do I get this to work with expo?

@palicko
Copy link

palicko commented May 19, 2022

@duggster it seems you don't have @babel/preset-react present in your packages.
Install it with yarn (or npm), like this yarn add @babel/preset-react --dev

@duggster
Copy link
Author

Thanks, got it installed and tried running it again but to no avail. I'm still only getting the normal log outputs same as my original post, nothing from wdyr. Anything else you can think of I might be missing? Are you able to post any relevant files that might have some difference to what I have in them?

Here is my updated wdyr.js and babel.config.js files (the other files in my project are still the same as my first post). I also tried removing the check for __DEV__ just to make sure that wasn't skipping the require( ) unexpectedly. I also upgraded expo to SDK45 and wdyr to 7.0.1.

wdyr.js

import React from 'react';

const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React, {
  trackAllPureComponents: true,
});

babel.config.js

module.exports = function (api) {
  api.cache(true);

  return {
    presets: [
      'babel-preset-expo',
      [
        '@babel/preset-react',
        {
          importSource: '@welldone-software/why-did-you-render',
          runtime: 'automatic',
        },
      ],
    ],
  };
};

package.json

{
  "name": "wdyr-test",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "expo": "^45.0.0",
    "expo-status-bar": "~1.3.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-native": "0.68.2",
    "react-native-web": "0.17.7"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/preset-react": "^7.17.12",
    "@welldone-software/why-did-you-render": "^7.0.1"
  },
  "private": true
}

@palicko
Copy link

palicko commented May 20, 2022

@duggster yes, forgot to add development parameter as well. I edited my previous post.

@duggster
Copy link
Author

Thanks @palicko , I added that however I'm still not getting any wdyr log output. I confirmed my expo project is running in Development mode.

babel.config.js

module.exports = function (api) {
  api.cache(true);

  return {
    presets: [
      'babel-preset-expo',
      [
        '@babel/preset-react',
        {
          importSource: '@welldone-software/why-did-you-render',
          runtime: 'automatic',
          development: process.env.NODE_ENV === 'development' || false,
        },
      ],
    ],
  };
};

logs:

iOS Bundling complete 2353ms
iOS Running app on Laptop
App RENDER
Subcomponent RENDER
Increment Pressed
App RENDER
Subcomponent RENDER
Increment Pressed
App RENDER
Subcomponent RENDER
Increment Pressed
App RENDER
Subcomponent RENDER

I'm expecting for wdyr to log that Subcomponent is re-rendering unnecessarily due to its style prop.

@palicko
Copy link

palicko commented May 20, 2022

@duggster I did the exact steps you described and created new project with same files as you have. Everything is working fine and I get this in my console:

Increment Pressed
App RENDER
_c2
Object {
  "_c2": [Function _c2],
} Re-rendered because of props changes:
props.style
different objects that are equal by value. (more info at http://bit.ly/wdyr02)
Object {
  "prev style": Object {
    "backgroundColor": "blue",
    "borderRadius": 50,
    "height": 100,
    "width": 100,
  },
} !== Object {
  "next style": Object {
    "backgroundColor": "blue",
    "borderRadius": 50,
    "height": 100,
    "width": 100,
  },
}
Object {
  "For detailed diff, right click the following fn, save as global, and run: ": [Function diffFn],
}
Subcomponent RENDER

Maybe try to clear Expo cache?

@duggster
Copy link
Author

@palicko thanks for confirming it works with expo at least, must be something unique to me going on here. Still not working for me even after clearing expo cache, and I tried deleting node_modules too. Next I will try starting from scratch again with another new project and will report back if it works.

@zagoorland
Copy link

These solutions also are not working for me on Expo 46 :/

@DarWiM
Copy link

DarWiM commented Sep 16, 2022

Works for me on Expo 46
npx cross-env NODE_ENV=development expo start -c

@mrzmyr
Copy link

mrzmyr commented Oct 11, 2022

@palicko actually got it working by clearing the cache as well.

Expo SDK Version 46

yarn install --dev @babel/preset-react @welldone-software/why-did-you-render

package.json

"main": "node_modules/expo/AppEntry.js",

babel.config.js

module.exports = function (api) {
  api.cache(true);
  return {
    presets: [
      "babel-preset-expo",
      [
        '@babel/preset-react',
        {
          importSource: '@welldone-software/why-did-you-render',
          runtime: 'automatic',
          development: true,
        },
      ],
    ],
    plugins: ["react-native-reanimated/plugin"],
  };
};

wdyr.js

import React from 'react';

if(__DEV__) {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React, {
    trackAllPureComponents: true,
  });

  console.log('whyDidYouRender enabled');
}

App.tsx

import './wdyr.js'
import { StatusBar } from 'expo-status-bar';
import { View } from 'react-native';
import useCachedResources from './hooks/useCachedResources';
import Navigation from './navigation';

export default function App() {
  const isLoadingComplete = useCachedResources();
  
  if (!isLoadingComplete) {
    return null;
  } else {
    return (
      <View style={{ flex: 1 }}>
        <Navigation />
        <StatusBar />
      </View>
    );
  }
}

Run expo with clearing the cache beforehand:

expo start -c

@Nantris
Copy link

Nantris commented Oct 26, 2022

@mrzmyr with what Expo SDK version?

I've spent hours trying to make this work. It doesn't work. I've created an issue on the Expo issue tracker: expo/expo#19709

@mrzmyr
Copy link

mrzmyr commented Oct 26, 2022

@slapbox Version is SDK 46

@Nantris
Copy link

Nantris commented Oct 26, 2022

Utterly baffling. I tried three separate projects, dozens of configs, and not one of them worked. @mrzmyr can you share the main field in your package.json - if you have one?

Edit: @#$%ing StrictMode. Turn it off.

@mrzmyr
Copy link

mrzmyr commented Oct 27, 2022

@slapbox

package.json

"main": "node_modules/expo/AppEntry.js",

@bayramn
Copy link

bayramn commented Dec 4, 2022

Hey guys, it stopped working all of sudden and just can't make it work anymore. Anyone can give a guidance to resolve this? I am on Expo SDK 46 on development built.

@RicardoBrito1938
Copy link

  const isLoadingComplete = useCachedResources();

Just to let everyone aware, it works on SDK 47 too

@henkaumio
Copy link

henkaumio commented May 10, 2023

Cant get WDYR to work/log anything in Expo 48. Followed all the steps above.

export const Screen = () => {
  const [toggle, settoggle] = useState(false);
  return (
    <Page>
      <DefaultButtonSelectableTextFullWidth
        onPress={() => settoggle(!toggle)}
        selectState={toggle ? 'selected' : 'unselected'}
        title="toggle"
      />
      <TestWDYR style={{ height: 50 }} />
      <__________v48 />
    </Page>
  );
};

const TestWDYR = ({ style }: { style: ViewStyle }) => {
  console.log('renderrred');
  return <View style={style} />;
};

TestWDYR.whyDidYouRender = true;

@felixSchl
Copy link

@henkaumio if you copy and pasted from above solutions, be sure to set NODE_ENV=development or change the babel.config.js to set development: true to confirm that's the problem.

@ErionTp
Copy link

ErionTp commented Sep 2, 2023

Maybe try npx cross-env NODE_ENV=development expo start -c

@MCervenka
Copy link

i just changes wdyr.js as this and got it working in expo 49:
if (__DEV__) { const whyDidYouRender = require('@welldone-software/why-did-you-render'); whyDidYouRender(React, { trackAllPureComponents: true, }); }

but it was showing me only one component rerendering. I fixed it, but the component that is all the time console.logging was not shown in wdyr

@antoinegrelard
Copy link

Hey all!

I've been playing around with the lib and try to figure out why I was unable to get it working as well.

I've ended up finding a solution that works for me and that will hopefully fix it for you all as well!

In my case I use:

  • Expo (v50)
  • babel-preset-expo (v10)
  • wdyr (v8)

What I noticed by digging in the babel-preset-expo code is that they already use the @babel/preset-react preset there, and you can pass params to it.

Here's what my babel.config.js file looks like:

module.exports = function (api) {
  api.cache(true);
  return {
    presets: [
      [
        "babel-preset-expo",
        {
          jsxImportSource: "@welldone-software/why-did-you-render",
        },
      ],
    ],
    plugins: [
      ["babel-plugin-react-docgen-typescript", { exclude: "node_modules" }],
      "react-native-reanimated/plugin",
    ],
  };
};

Notice how here I pass the importSource as jsxImportSource to babel-preset-expo directly.

With that done, I started expo (expo start -c) and I can now see all the logs that I need!

Hope this helps anyone who comes across the issue again!

@markwitt1
Copy link

What if we already have a jsxImportSource? For example nativewind?

@Nantris
Copy link

Nantris commented Nov 25, 2024

@markwitt1 I'm no expert, but I would think you'd simply be out of luck in such a case unless nativewind provides a way to handle this.

@luffy-taro
Copy link

@markwitt1 You can pass an array jsxImportSource: ["nativewind","@welldone-software/why-did-you-render"]. I think this works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.