Skip to content

v4.x: Orphaned stylesheets due to skipped effect in useSynchronousEffect #46862

@ostgals

Description

@ostgals

Steps to reproduce

Demo: https://codesandbox.io/p/sandbox/mui4-make-styles-repro-c7h95p?file=%2Fsrc%2FList.js%3A19%2C22

Steps:

  1. Switch the list on by clicking TOGGLE LIST.
  2. Observe that stylesheet LIST appears.
  3. Switch the list off by clicking TOGGLE LIST button again.
  4. Observe that stylesheet LIST is not removed.

Current behavior

LIST stylesheet remains in the DOM after the component is unmounted, leading to potential memory leaks and stale styles.

Expected behavior

LIST stylesheet should be properly detached and cleaned up even when React skips effects due to state updates during render.

Context

In our legacy project, we dynamically mount one of several applications on the page at any given time. Each application is delivered as a separate bundle and includes its own instance of Material-UI. We commonly use state updates during render to optimize our workflow. As a result, we’ve encountered some similar issues where stylesheets from a previously mounted application are not properly cleaned up, leading to conflicts with the styles of the currently mounted application.

We investigated a bit this issue and found out that it occurs because useSynchronousEffect stores its cleanup function in a local variable, which is lost if React skips the effect.

Also we fixed the issue by using a ref for the cleanup function, so it persists across renders and ensure proper cleanup.

For now we have patched makeStyles module locally. I'm going to create PR later.

Your environment

Browser: Chrome (latest)
Material UI version: 4.11.3
React: ^17

Search keywords: useSynchronousEffect, orphaned stylesheets, effect skipping, React, makeStyles, cleanup bug

Metadata

Metadata

Assignees

No one assigned

    Labels

    scope: stylesSpecific to @mui/styles. Legacy package, @material-ui/styled-engine is taking over in v5.v4.x

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions