Skip to content

Custom contentComponent in Drawer re-render everytime #6718

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

Closed
sanjeevyadavIT opened this issue Sep 14, 2019 · 18 comments
Closed

Custom contentComponent in Drawer re-render everytime #6718

sanjeevyadavIT opened this issue Sep 14, 2019 · 18 comments

Comments

@sanjeevyadavIT
Copy link

Current Behavior

I have implemented a Drawer which host a Stack navigator inside. I am giving a custom component to be render in contentComponent in Drawer. But the custom component in Drawer keeps rendering after every:

  1. Whenever the Drawer is open
  2. Whenever the Drawer is close
  3. Any screen is open in Stack Navigator

Expected Behavior

  • custom component given to Drawer should not keep re rendering every time any screen is open from the stack

How to reproduce

  1. run git clone https://github.com/alexakasanjeev/magento_react_native.git && cd magento_react_native
  2. Change the branch to git checkout feature/react-navigation
  3. install dependency npm install
  4. In terminal type npm start
  5. In another terminal run react-native run-android
  6. Once the app is running in device, enable Debug Js Remotely from dev menu
  7. Open the console of chrome and click on any button in the App
  8. Every time any button is clicked to open new screen, the custom component keeps re-rendering as seen from console logs

Rendering Drawer Navigation!

Screenshots

Screenshot from 2019-09-14 16-26-43

Your Environment

software version
@react-navigation/core ^5.0.0-alpha.8
@react-navigation/native ^5.0.0-alpha.7
@react-navigation/drawer ^5.0.0-alpha.8
@react-navigation/stack ^5.0.0-alpha.15
react-native 0.60.4
node v10.15.3
yarn 1.17.3
@satya164
Copy link
Member

What is the problem with re rendering?

@sanjeevyadavIT
Copy link
Author

sanjeevyadavIT commented Sep 14, 2019

The premise of React is that you let React optimize updates for you so you don't have to think about re-renders.

I'm using PureComponent, but still its keep re rendering

Is it actually causing any slow down in your app? If it is causing a slow down and your custom component is heavy, you can optimize your component with PureComponent/React.memo manually.

Yes, and this problem is in react-navigation@4.x , I wanted to move away from that problem that's why I was trying react-navigation@5.x api

@sanjeevyadavIT
Copy link
Author

Also as Home (the root screen) is render only once, doesn't matter how many screen you open in stack or press back button, same functionality should be of Drawer

@satya164
Copy link
Member

If the component re render everytime even if it is not used, it is waste of render and potential slow down for the APP.

The premise of React is that you let React optimize updates for you so you don't have to think about re-renders.

Is it actually causing any slow down in your app? If it is causing a slow down and your custom component is heavy, you can optimize your component with PureComponent/React.memo manually.

why it keeps re-rendering

Because navigation state is nested. Changing child state changes state of parent.

@sanjeevyadavIT
Copy link
Author

sanjeevyadavIT commented Sep 14, 2019

Bro I have used PureComponent, it's not working

this is the same issue as
#2507

@satya164
Copy link
Member

That's a completely different report regarding unmounting on navigating away.

Bro I have used PureComponent, it's not working

You can't just put PureComponent on the custom component and expect it to work. It is re-rendering because its props are changing. Pure component won't prevent that. If we could automatically prevent the re-render, we would.

You'll need to extract expensive parts out to separate component, pass the minimum required data as props to it, and then apply React.memo/PureComponent.

@sanjeevyadavIT
Copy link
Author

sanjeevyadavIT commented Sep 14, 2019

Can you atleast look once in my code, there is nothing expensive, i have created dummy views, they just contain a button to navigate to different screen, there is no business logic in it, Even the custom, drawer component just has a button to close the drawer

This is my Home component looks like
Screenshot_1568462902

This is my custom drawer component
Screenshot_1568462906

They are literally just views with button and no state no props nothing

@satya164
Copy link
Member

As I mentioned, the child navigation state changes which causes parent state to change. Re-rendering the component is expected behaviour and not a bug.

If the view is simple, why do you care about re-rendering? If there's nothing expensive then you don't need to prevent re-render. Is it actually causing performance issues for you?

@sanjeevyadavIT
Copy link
Author

sanjeevyadavIT commented Sep 14, 2019

Bro this is my actual screen,(I'm testing on dummy that I showed you above)
1

Drawer screen
2

now the custom drawer component keeps re-rendering even if I don't click anything, and no state or no async operation is happening, nothing, and the drawer component re renders in react-navigation@4.x which is making my app slow

to prevent that i'm trying react navigation@5.x so that once drawer component loads it doesn't re-render on its own, although the drawer component doesn't re-render on its own, but it is re-rendering whenever I am changing screen

@sanjeevyadavIT
Copy link
Author

Please atleast once, please just clone the repo, change it to branch feature/react-navigation and install dependency and just see for yourself, I may not be able to explain you the issue but please just run the code, and then tell me if it's a bug or not

@satya164
Copy link
Member

If your drawer is expensive to re-render, extract the expensive parts to separate component and apply pure component.

class MyCustomComponent extends PureComponent {
  // ... your expensive component
}


const ContentComponent = ({ navigation }) => {
  // Don't pass all the props so we don't trigger re-render
  // Only pass required props
  return <MyCustomComponent navigation={navigation} />
}

// ...

<Drawer.Navigator contentComponent={ContentComponent} />

React Navigation cannot optimize your component. Only you know what props can safely trigger a re-render and what props cannot in your custom component.

@satya164
Copy link
Member

Please atleast once, please just clone the repo, change it to branch feature/react-navigation and install dependency and just see for yourself, I may not be able to explain you the issue but please just run the code, and then tell me if it's a bug or not

Dude, I already told you its expected behaviour. I won't find something new by running your code. I already know that the custom component will re-render.

If re-render is expensive in your case, you need optimize your custom component manually. React Navigation cannot prevent re-render automatically for the reason I mentioned.

@sanjeevyadavIT
Copy link
Author

sanjeevyadavIT commented Sep 14, 2019

bro this is my custom component, which keeps re-rendering, could you tell me which part should I extract it out

const DrawerPage = () => {
    console.log('Rendering Drawer Navigation!');
    return (
      <View>
        <Text>DrawerPage</Text>
        <Button
          title="Close Drawer"
          onPress={() => this.props.navigation.toggleDrawer()}
        />
      </View>
    );
}

@satya164
Copy link
Member

satya164 commented Sep 14, 2019

See my code https://github.com/react-navigation/navigation-ex/issues/99#issuecomment-531475410

Put your custom component and console.log inside MyCustomComponent

@sanjeevyadavIT
Copy link
Author

sanjeevyadavIT commented Sep 14, 2019

I did that, now only ContentComponent is rendering, MyCustomComponent is not re-rendering every time

Thank you so much for your help and your patience

@satya164 satya164 transferred this issue from react-navigation/navigation-ex Feb 7, 2020
@kapilbhosale
Copy link

I was also facing the same issue, here is how I managed to solve mine.
Hope this will help you.

logic: check if the drawer is open or close, return without doing heavy stuff if the drawer is closed.

  import {useIsDrawerOpen} from '@react-navigation/drawer';
  ..
  ..
  const isDrawerOpen = useIsDrawerOpen();
  if (!isDrawerOpen) {
    return(<></>)
  }

@BlazeGawlik
Copy link

I see you are using react-navigation 5, the umountOnBlur option worked great for me: https://stackoverflow.com/a/62675176/5970652

@github-actions
Copy link

github-actions bot commented Sep 5, 2021

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants