Material-ui: [Accordion] renders components even when it's closed.

Created on 7 Mar 2018  路  10Comments  路  Source: mui-org/material-ui

Does this library render components even when they are hidden? For example, ExpansionPanel. It appears that this component renders everything inside even when it's closed by default. What if you have components inside of there that have extensive functionality going on and you had 20 expansion panels doing the same thing and the user only opened one of them? Doesn't this seem inefficient running through functionality of several components that may never even be seen by the user?

I am aware that I could potentially look at the onClick function and find out if the panel is expanded or not then render the component, but it seems like this should be a default behavior of the ExpandedPanel or any component that show/hides components.

  • [ x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

Only render components inside the ExpansionPanel when it's open. Unmount components inside the ExapansionPanel when it is closed.

Current Behavior

Renders component regardless if the ExpansionPanel is open or closed.

Steps to Reproduce (for bugs)

Check out the console.logs for the sandbox below. They kick off regardless of the ExpansionPanel being closed.
https://codesandbox.io/s/lyo2m9ky0q

Accordion enhancement good first issue

Most helpful comment

Just an update, on version 4.2.1 uses TransitionProps

<ExpansionPanel TransitionProps={{ mountOnEnter: true }}>

All 10 comments

@jbsmith969 This issue shares some root cause with #10183. You are free to change the behavior. The following option disables the rendering of the component in the DOM.

<ExpansionPanel CollapseProps={{ unmountOnExit: true }}>

https://codesandbox.io/s/p9z3jk639x

it seems like this should be a default behavior of the ExpandedPanel or any component that show/hides components.

This is an interesting point to discuss. It's a tradeoff. By not mounting the hidden content you will make the content unreachable for SEO and increase the responsiveness as more work is going to be needed by the browser to display the content at the click interaction. On the other hand, mounting everything makes to initial reconciliation of the page slower.
I'm happy to change the default behavior of the ExpansionPanel. Do you want to submit a pull request?

I would like to chip in here, i have a usecase where it is benefitial to have to content rendered all the time to make form submits easier (even if they are not visible). It's a settings page where the expansionPanel is used to seperate the form into sections (where some details are most of the time not really important).
Would be great if there would be a solution where it is up to the user to decide if the expansion panel content should render initially (i guess unmountOnExit is this option already?).
Besides that, if the use case of not rendering at first is more often used then it probably makes sense to make this the default behaviour and adapt the documentation to inform users about this.

@oliviertassinari I had the same issue, and the CollapseProps works for me, thanks. Personally, I think not rendering children unless the panel is open is more intuitive.

Hey @oliviertassinari! Thanks for the response. Sorry, I must have missed that unmountOnExit prop when searching through docs. Do you think we could make that name a little more intuitive since it seems to also prevent rendering from your description? That may have been why I missed it. I'll give that prop a shot to see if that works. If I can find some time, I'll try to make some changes to the code and make a pull request. I'm leaning towards not rendering children by default and a prop to render children for cases like SEO and what @Loktor brought up.

Would be great if there would be a solution where it is up to the user to decide if the expansion panel content should render initially

@Loktor I agree, it's a problem we have already been facing and solved on the Modal side: #10572.

Besides that, if the use case of not rendering at first is more often used then it probably makes sense to make this the default behavior and adapt the documentation to inform users about this.

Yes, I do think that the unmounting should be the default behavior. You will most likely render many items with the ExpansionPanel component. It can greatly improve the initial rendering this way.

Sorry, I must have missed that unmountOnExit prop when searching through docs.

@jbsmith969 You won't find this key in our documentation. It's a property implemented by react-transition-group library.

If I can find some time, I'll try to make some changes to the code and make a pull request.

Oh great! I think that we should implement the same approach than with the Modal: a keepMounted property. I will let you the lead on this issue :).

If no one has picked it up yet , I'd like to give this one a go

@oliviertassinari Don't we need to set {mountOnEnter: true} to prevent an ExpansionPanel from rendering hidden child components when it's first mounted? I don't see the point of using unmountOnExit here for most use cases.

mountOnEnter
By default the child component is mounted immediately along with the parent Transition component. If you want to "lazy mount" the component on the first in={true} you can set mountOnEnter. After the first enter transition the component will stay mounted, even on "exited", unless you also specify unmountOnExit.

type: boolean
default: false

unmountOnExit
By default the child component stays mounted after it reaches the 'exited' state. Set unmountOnExit if you'd prefer to unmount the component after it finishes exiting.

type: boolean
default: false
http://reactcommunity.org/react-transition-group/transition

If you use the unmount option, is the content still on the page for Readers? If the content is not on the page, then this is not an accessible option. I solved this yesterday but looping through the links and toggling the tabIndex between -1 and 0, which seems to have the proper functioning, but it would be nice if this behavior was not only baked in but default.

Just an update, on version 4.2.1 uses TransitionProps

<ExpansionPanel TransitionProps={{ mountOnEnter: true }}>

We've added a section to our docs describing different tradeoffs:

The content of ExpansionPanels is mounted by default even if the panel is not expanded. This default behavior has server-side rendering and SEO in mind. If you render expensive component trees inside your panels or simply render many panels it might be a good idea to change this default behavior by enabling the unmountOnExit in TransitionProps: . As with any performance optimization this is not a silver bullet. Be sure to identify bottlenecks first and then try out these optimization strategies.

-- https://material-ui.com/components/expansion-panels/#performance

Was this page helpful?
0 / 5 - 0 ratings

Related issues

iamzhouyi picture iamzhouyi  路  3Comments

zabojad picture zabojad  路  3Comments

reflog picture reflog  路  3Comments

ghost picture ghost  路  3Comments

sys13 picture sys13  路  3Comments