Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TextField] MuiOutlinedInput callback in styleOverrides sometimes passes ownerState as undefined #31982

Closed
2 tasks done
Lani opened this issue Mar 25, 2022 · 4 comments 路 Fixed by #33241
Closed
2 tasks done
Assignees
Labels
bug 馃悰 Something doesn't work component: text field This is the name of the generic UI component, not the React module!

Comments

@Lani
Copy link

Lani commented Mar 25, 2022

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 馃槸

The ownerState parameter in the example below is sometimes undefined:

const theme = createTheme({
  components: {
    MuiOutlinedInput: {
      styleOverrides: {
        root: ({ ownerState }) => {
         // ownerState is sometimes undefined.
          console.log("MuiOutlinedInput ownerState", ownerState);
          return {};
        }
      }
    },
});

Expected behavior 馃

The ownerState parameter should never be undefined.

Workaround

Return an empty object if ownerState is undefined.

Steps to reproduce 馃暪

Steps:
See https://codesandbox.io/s/ownerstate-undefined-muioutlinedinput-theme-forked-vv40l9?file=/demo.tsx

  1. Just let the page render.
  2. Check the console log, ownerState logged as undefined.

Context 馃敠

Trying to override border color on MuiOutlinedInput.

Your environment 馃寧

`npx @mui/envinfo`
System:
    OS: Linux 4.19 Ubuntu 20.04.3 LTS (Focal Fossa)
  Binaries:
    Node: 14.15.4 - ~/.nvm/versions/node/v14.15.4/bin/node
    Yarn: Not Found
    npm: 7.24.1 - ~/.nvm/versions/node/v14.15.4/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: Not Found
  npmPackages:
    @emotion/react: ^11.7.0 => 11.7.0 
    @emotion/styled: ^11.6.0 => 11.6.0 
    @mui/lab: ^5.0.0-alpha.56 => 5.0.0-alpha.65 
    @mui/material: ^5.3.0 => 5.3.0 
    @mui/styles: ^5.3.0 => 5.3.0 
    @mui/system: ^5.3.0 => 5.3.0 
    @mui/utils: 5.3.0 => 5.3.0 
    @types/react: ^17.0.37 => 17.0.37 
    react: ^17.0.2 => 17.0.2 
    react-dom: ^17.0.2 => 17.0.2 

Browser: Microsoft Edge Version 99.0.1150.46 (Officiell version) (64 bitar)

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2019",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "noFallthroughCasesInSwitch": true,
    "useDefineForClassFields": true,
    "types": [
      "reflect-metadata",
      "node",
      "jest"
    ],
    "stripInternal": true,
    "useUnknownInCatchVariables": false,
    "strictNullChecks": true,
    "noImplicitAny": true, 
    "noImplicitThis": true 
  }
} 
@Lani Lani added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Mar 25, 2022
@Lani Lani changed the title MuiOutlinedInput callback in styleOverrides somtimes passes ownerState as undefined MuiOutlinedInput callback in styleOverrides sometimes passes ownerState as undefined Mar 25, 2022
@danilo-leal danilo-leal changed the title MuiOutlinedInput callback in styleOverrides sometimes passes ownerState as undefined [TextField] MuiOutlinedInput callback in styleOverrides sometimes passes ownerState as undefined Mar 25, 2022
@danilo-leal danilo-leal added the component: text field This is the name of the generic UI component, not the React module! label Mar 25, 2022
@oliviertassinari oliviertassinari added bug 馃悰 Something doesn't work and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Apr 9, 2022
@oliviertassinari
Copy link
Member

oliviertassinari commented Apr 9, 2022

I got curious by these 3 logs, I was expecting only 1. It turns out 3 looks because there are 3 slots. Each slot tries to resolve the style of the Root, using its own props 馃檭. When we have:

const ButtonRoot = styled('button')({
  name: 'Button',
  slot: 'Root',
  overridesResolver: (props, styles) => styles.root,
})

const ButtonLabel = styled('button')({
  name: 'Button',
  slot: 'Label',
  overridesResolver: (props, styles) => styles.label,
})

<ButtonRoot ownerState={ownerState} data-testid="root">
  <ButtonLabel ownerState={ownerState} data-testid="label">Foo</ButtonLabel>
</ButtonRoot>

I fail to envision how we could justify having ButtonLabel resolving the styles on the ButtonRoot based on the props of ButtonLabel (e.g. data-test-id is wrong) to not use it in the end. In practice, my proposal is to restrict this feature https://mui.com/customization/theme-components/#overrides-based-on-props to only slots.

I could land on this fix, which makes more sense to me:

diff --git a/packages/mui-system/src/createStyled.js b/packages/mui-system/src/createStyled.js
index c7d3016d1b..f8cec2ad98 100644
--- a/packages/mui-system/src/createStyled.js
+++ b/packages/mui-system/src/createStyled.js
@@ -137,12 +137,17 @@ export default function createStyled(input = {}) {
           const styleOverrides = getStyleOverrides(componentName, theme);

           if (styleOverrides) {
-            const resolvedStyleOverrides = {};
-            Object.entries(styleOverrides).forEach(([slotKey, slotStyle]) => {
-              resolvedStyleOverrides[slotKey] =
-                typeof slotStyle === 'function' ? slotStyle(props) : slotStyle;
-            });
-            return overridesResolver(props, resolvedStyleOverrides);
+            if (componentSlot) {
+              const slotCamelCase = lowercaseFirstLetter(componentSlot);
+
+              if (styleOverrides[slotCamelCase] && typeof styleOverrides[slotCamelCase] === 'function') {
+                return overridesResolver(props, {
+                  [slotCamelCase]: styleOverrides[slotCamelCase](props),
+                });
+              }
+            }
+
+            return overridesResolver(props, styleOverrides);
           }

           return null;

@Louai99k
Copy link

I know this is closed but I didn't understand the solution. I'm using version 5.2.3 so that I didn't open a new issue so I want to ask is now the after the updates the ownerState will be received always because if so I will update to the latest version. Btw why when I console log the props from within styleOverrides it runs three times?

@mnajdova
Copy link
Member

I agree that the current implementation is not very intuitive, but also we cannot restrict each slot to run the style overrides only for that slot, because sometimes in one slot more style overrides are being added, like: https://github.com/mui/material-ui/blob/master/packages/mui-material/src/Button/Button.js#L259

I propose we go with @siriwatknp's fix for now, and revisit this in v6. I am adding it to the milestone.

@ZeeshanTamboli
Copy link
Member

ZeeshanTamboli commented Mar 27, 2023

To keep track for v6: Faced similar issue for the Select component in #36422. See #36422 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 馃悰 Something doesn't work component: text field This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants