base-ui
base-ui copied to clipboard
[TextareaAutosize] Unstable height when rendered in a Next.js RSC page
Steps to reproduce 🕹
Live example: https://codesandbox.io/p/sandbox/https-github-com-mui-material-ui-issues-38607-5h5ndr?file=%2Fsrc%2Fapp%2Fpage.tsx%3A22%2C1
Unstable height TextField multiline on nextjs app router when i reload the page. Same thing happens on page first load. For bug reproduction, i used material-ui-nextjs-ts from the example folder. Video below.
https://github.com/mui/material-ui/assets/57659794/a37ddb07-246a-478e-b360-73e6518836b9
Current behavior 😯
No response
Expected behavior 🤔
No response
Context 🔦
No response
Your environment 🌎
Expand
System: OS: Windows 10 10.0.19044 Binaries: Node: 16.16.0 - C:\Program Files\nodejs\node.EXE Yarn: Not Found npm: 8.11.0 - C:\Program Files\nodejs\npm.CMD Browsers: Chrome: 116.0.5845.97 Edge: Spartan (44.19041.1266.0), Chromium (116.0.1938.54) npmPackages: @emotion/react: latest => 11.11.1 @emotion/styled: latest => 11.11.0 @mui/base: 5.0.0-beta.11 @mui/core-downloads-tracker: 5.14.5 @mui/icons-material: latest => 5.14.3 @mui/material: latest => 5.14.5 @mui/private-theming: 5.14.5 @mui/styled-engine: 5.13.2 @mui/system: 5.14.5 @mui/types: 7.2.4 @mui/utils: 5.14.5 @types/react: latest => 18.2.21 react: 18.x => 18.2.0 react-dom: 18.x => 18.2.0 typescript: latest => 5.1.6
Search keywords:
@vladpaul09 I can reproduce this – as a workaround for now, you can wrap the component with NoSsr
to achieve the effect on load if the parent wasn't an RSC component/page, here's a working sandbox: https://codesandbox.io/p/sandbox/https-github-com-mui-material-ui-issues-38607-5h5ndr?file=%2Fsrc%2Fapp%2Fpage.tsx%3A22%2C1
For reference, here's how the TextareaAutosize
looks on load in a normal sandbox (no Next.js, no RSC) https://codesandbox.io/s/textareaautosize-no-rsc-s5cs9c
We don't have access to the DOM node on the server (as it doesn't exist there), so it's impossible to measure its height. I can't really think of another fix than the workaround suggested by @mj12albert.
As far as I know, it's a regression from mui/material-ui#35862. In the reproduction, the field is empty, there is no content to sync the layout with after hydration, so it doesn't matter of it's client-side or server-side rendered, we can fully rely on CSS
Simple fix:
diff --git a/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx b/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx
index 9f582765f6..b9a1b045d1 100644
--- a/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx
+++ b/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx
@@ -69,7 +69,7 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(
const shadowRef = React.useRef<HTMLTextAreaElement>(null);
const renders = React.useRef(0);
const [state, setState] = React.useState<State>({
- outerHeightStyle: 0,
+ outerHeightStyle: undefined,
});
const getUpdatedState = React.useCallback(() => {
To make the types passs is tricker, maybe:
diff --git a/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx b/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx
index 9f582765f6..7786524b89 100644
--- a/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx
+++ b/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx
@@ -10,9 +10,14 @@ import {
} from '@mui/utils';
import { TextareaAutosizeProps } from './TextareaAutosize.types';
+type InitialState = {
+ outerHeightStyle: undefined;
+ overflow?: boolean;
+};
+
type State = {
outerHeightStyle: number;
- overflow?: boolean | undefined;
+ overflow?: boolean;
};
function getStyleValue(value: string) {
@@ -68,8 +73,8 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(
const handleRef = useForkRef(forwardedRef, inputRef);
const shadowRef = React.useRef<HTMLTextAreaElement>(null);
const renders = React.useRef(0);
- const [state, setState] = React.useState<State>({
- outerHeightStyle: 0,
+ const [state, setState] = React.useState<InitialState | State>({
+ outerHeightStyle: undefined,
});
const getUpdatedState = React.useCallback(() => {
@@ -127,7 +132,7 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(
return { outerHeightStyle, overflow };
}, [maxRows, minRows, props.placeholder]);
- const updateState = (prevState: State, newState: State) => {
+ const updateState = (prevState: State | InitialState, newState: State) => {
const { outerHeightStyle, overflow } = newState;
// Need a large enough difference to update the height.
// This prevents infinite rendering loop.
Before
https://github.com/mui/material-ui/assets/3165635/3b32168c-f61d-49d8-a620-09d79d2fd7d6
After
https://github.com/mui/material-ui/assets/3165635/4de5a168-468e-4609-8b7a-1e6032f0fad5
@mj12albert @michaldudak @oliviertassinari we would like to pick this up
Any update on this?
I'm also having the Unstable height when setting the TextField with multiline in nextjs 14. Are there any update. how could fix the isssue
Working on the Base UI components' API changes is our top priority at the moment. Since these changes may affect the internals of the components, we don't want to focus on fixing bugs as there's a risk that this work may be unnecessary. When we have a consistent new API across all the existing components, we'll resume accepting contributions and focus more on bug fixes.