material-ui: [transitions] "Cannot read property `scrollTop` of null"

  • The issue is present in the latest release.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 😯

If the child of <Transition> components does not forwardRef to DOM, it cause this error.

Screen Shot 2564-07-07 at 09 24 14

Expected Behavior 🤔

The error should be more informative about how to fix it.

Steps to Reproduce 🕹

Steps:

  1. open this sandbox https://codesandbox.io/s/transition-v5-error-dide8?file=/src/App.tsx
  2. change material-ui/core to v5.beta
  3. will see the error

Context 🔦

Is it better to display warning (in console) instead of Error?

Here is what I think about the dev experience.

  • write the code (use Transition the wrong way, no forwardRef for child)
  • check in browser, it does not work (the ui display without transitioning)

then, 3 possibilities

  • they see the warning in console about why it does not work and link to full doc example
  • they go to Transition docs
  • worse case, they open the issue

Actions

Your Environment 🌎

`npx @material-ui/envinfo`
  Don't forget to mention which browser you used.
  Output from `npx @material-ui/envinfo` goes here.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 17
  • Comments: 16 (3 by maintainers)

Commits related to this issue

Most upvoted comments

Also facing the same problem… so are you saying that if the child is a styled-component and does not have a forwardRef it would not work…? Shouldn’t the Fade (or all transitions) work with or without a ref?

We have many components that are just plain styled-components without a ref (because there were simply no need to use a ref) but now we have to add it everywhere just to get transition to work??

Perhaps all transitions should wraps the child with a plain div instead?

The workaround I had to do, was to manually wrap the children with another div… 👎

      <Fade in={visible} timeout={1000}>
        <div>{children}</div>
      </Fade>

Thanks - this saved me some debugging. I had this construct:

<Zoom in timeout={200}>
  <React.Fragment>

Fixed by adding the actual components as the only child, e.g.,

<Zoom in timeout={200}>
  <Fab>

This issue is still existing and was not available with MUI 4. This can cause the a project with hundreds of components to crash after the upgrade to MUI 5 and it’s difficult to fix because the stack trace or the logged error message is not helpful at all as it doesn’t mention where or which MUI component is causing the issue.

yeah so … how to use transitions on mounting / rerendering components with MUI5 then ? any solution? any workaround ? or is this only affecting Fade ?

@codingedgar I think the problem is in the PasswordInput. You have to forward the ref to the Input.

export const PasswordInput = styled(
  React.forwardRef(({ showPassword, onToggleShowPassword, ...props }: PasswordInputProps, ref) => (
    <Input
      ref={ref}
      placeholder="Link Password"
      type={showPassword ? "test" : "password"}
      endAdornment={
        // eslint-disable-next-line react/jsx-wrap-multilines
        <InputAdornment position="end">
          <IconButton
            aria-label="toggle password visibility"
            edge="end"
            onMouseDown={(e) => {
              e.preventDefault();
            }}
            onClick={onToggleShowPassword}
          >
            {showPassword ? (
              <VisibilityOff fontSize="small" />
            ) : (
              <Visibility fontSize="small" />
            )}
          </IconButton>
        </InputAdornment>
      }
      {...props}
    />
  ))
)

@totszwai Can confirm this solution of wrapping in a div works. Can you please look into this MUI team? We shouldn’t have to resort to this workaround.