Material-ui: [Stepper] Document how to avoid re-mounting between each step

Created on 9 Sep 2020  路  17Comments  路  Source: mui-org/material-ui

In my application, I was rendering two different material-tables in two different steps of the Stepper component. When trying to test switching between steps quickly it would begin slowing down considerably and eventually freeze (in which I had to close the browser tab to continue).

I'm not sure the process for contributing code so I'm attaching below how I went around this by instead setting display: none; on all non-active steps.

interface StepContentProps {
    component: any;
    props?: any;
}

interface ContentProps {
    stepContent: StepContentProps[];
    activeStep: number;
}

const StepContent = ({ stepContent, activeStep }: ContentProps) => {
    return (
        <>
            {stepContent.map(({ component: Component, props }, index) => {
                return (
                    <Component key={index} style={{ display: activeStep === index ? 'inherit' : 'none' }} {...props} />
                );
            })}
        </>
    );
};

Here's an example of what the array of StepContentProps looks like:

const stepContent: StepContentProps[] = [
        {
            component: MaterialTable,
            props: {
                title: 'Users',
                columns: userColumns as Column<User | Inventory>[],
                data: users,
                options: { selection: true, filtering: true, tableLayout: 'auto' },
                onSelectionChange: (rows) => {
                    setSelectedUsers(rows);
                },
            } as MaterialTableProps<User>,
        }
]
Stepper docs good first issue performance

All 17 comments

@alehechka What makes you believe that the issue is on the Material-UI side? What's happening if you replace material-table with the work in progress data grid?

Please provide a minimal reproduction test case. This would help a lot 馃懛 .
A live example would be perfect. This codesandbox.io template _may_ be a good starting point. Thank you!

@alehechka I'm working on something that also requires the stepper to stop unmounting the when it is inactive. Can you please tell me what you changed and where you changed it for your solution to work? I'm not familiar with TS but I can try.

@doodhJalebi Thanks for the question, now I think I understand what problem @alehechka was facing. What about we update the documentation to include: https://material-ui.com/components/accordion/#performance. I believe the problem is the same. We can leverage the same solution: add the same section in the documentation.

@oliviertassinari that would be just perfect! Quick question: would this update to the docs be a patch or will I have to wait till v5 comes out?

@doodhJalebi This has been supported since v1. The documentation would be on v5 (next branch). Do you want to give it a try? :)

@oliviertassinari I would love to give it a try (only if its not too much of a hassle for you).

@oliviertassinari Thanks for updating this to be a doc related issue, I think that's definitely the route to go since I don't think this is the fault of material-ui. I was originally following the Stepper docs here.

In the example code it uses the function getStepContent that will return the text to be used on that step. I changed that up a bit to instead supply the actual material-table component to be rendered. But due to the intensity of re-mounting the material-table so often is what caused the slow down. My solution provided above was to instead keep all components mounted but hidden when its step is not active.

@doodhJalebi Go ahead, it will save us time. Note that the tradeoff of the Stepper is opposite to the Accordion. We don't mount all the steps to speed up the initial mount.

@oliviertassinari sorry for going AWOL. Um, noob questions but uh when you say "go ahead" or "give it a try", where do I go exactly? I apologize for my confusion 馃槙

@doodhJalebi I was referring to opening a pull request. However, looking back at the problem, it doesn't seem to be a frequent request. I'm closing. An answer on GitHub' issue is already something developers can search and find (if they spend enough time)

hi @oliviertassinari

Is it right that material-ui library re-mounts every step inside the stepper when switching back and forward between the steps? If so, how could I prevent this functionality?

Currently I am experiencing issues with the stat being reset to default on switching back and forward. Also with an instance of formik and formik persists after going back and forward twice, the formik persist state is also reset to defaults.

Looking forward for your answer.

Thanks!

@kevinvugts Are you using the vertical stepper? I think that the behavior is correct. You will find #10569 for developers advocating for the current behavior. I'm reopening as, after all, we might benefit from documentation about it. The following should be enough:

diff --git a/docs/src/pages/components/steppers/steppers.md b/docs/src/pages/components/steppers/steppers.md
index 34004243f6..25a8c6c373 100644
--- a/docs/src/pages/components/steppers/steppers.md
+++ b/docs/src/pages/components/steppers/steppers.md
@@ -70,6 +70,16 @@ Vertical steppers are designed for narrow screen sizes. They are ideal for mobil

 {{"demo": "pages/components/steppers/VerticalLinearStepper.js"}}

+### Performance
+
+The content of a step is unmounted when closed.
+If you need to make the content available to search engines or render expensive component trees inside your modal while optimizing for interaction responsiveness
+it might be a good idea to keep the step mounted with:
+
+```jsx
+<StepContent TransitionProps={{ unmountOnExit: false }} />
+```
+
 ## Mobile stepper

 This component implements a compact stepper suitable for a mobile device. It has more limited functionality than the vertical stepper. See [mobile steps](https://material.io/archive/guidelines/components/steppers.html#steppers-types-of-steps) for its inspiration.

What do you think about it? Do you want to open a pull request?

+it might be a good idea to keep the step mounted with:

Hi @oliviertassinari

Thanks for your prompt reply!

I am using the Horizontal Stepper at the moment. Does this component also has access to the TransitionProps?
TransitionProps={{ unmountOnExit: false }}

@kevinvugts The horizontal stepper doesn't have this notion, so I think that you are looking at the wrong place.

@kevinvugts The horizontal stepper doesn't have this notion, so I think that you are looking at the wrong place.

What would be the solution for the Horizontal Stepper? Is there a way I could prevent the unmounting components?

@kevinvugts The horizontal stepper doesn't have this notion, so I think that you are looking at the wrong place.

What would be the solution for the Horizontal Stepper? Is there a way I could prevent the unmounting components?

@oliviertassinari Is there a possibility to solve the unmounting Steps in Horizontal Stepper in a different way? Currently it's causing issues in my app. It would be awesome if you had some suggestions. :)

@kevinvugts You can ask on StackOverflow. For the horizontal stepper, this is coming from your application's code, the stepper only displays the header, not the body.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

finaiized picture finaiized  路  3Comments

rbozan picture rbozan  路  3Comments

sys13 picture sys13  路  3Comments

chris-hinds picture chris-hinds  路  3Comments

reflog picture reflog  路  3Comments