Repository: mui/material-ui (TypeScript)
Date: 2022-08-03 07:26:22+00:00
Task type: Bug Fix

Issue:
[System] MUI duplicates `sx` props when it's used with `component` prop 
### Duplicates

- [X] I have searched the existing issues

### Latest version

- [X] I have tested the latest version

### Current behavior 😯

If we specify another component in `component` prop and provide `sx` prop, MUI duplicates everything in `sx` and generates redundant `style` tags. 

```tsx
<Box component={Box} sx={{background: 'red', span: {color: 'blue'}}}>
  <span>Test</span>
</Box>
```

if we inspect `div` and `span` styles, we can find following - 
<img width="380" alt="Screen Shot 2022-07-09 at 14 51 16" src="https://user-images.githubusercontent.com/5411244/178104593-d084d749-7b14-4d94-9779-d2ef9f89af2e.png">
<img width="376" alt="Screen Shot 2022-07-09 at 14 53 54" src="https://user-images.githubusercontent.com/5411244/178104595-217c2884-a29e-424d-a1d0-a2e78c97a5a0.png">

Also, it generates following `style` tags  - 
```html
<style data-emotion="css" data-s="">.css-1tv1eg2{background:red;}</style>
<style data-emotion="css" data-s="">.css-1tv1eg2 span{color:blue;}</style>
<style data-emotion="css" data-s="">.css-1fhbb51{background:red;background:red;}</style>
<style data-emotion="css" data-s="">.css-1fhbb51 span{color:blue;}</style>
<style data-emotion="css" data-s="">.css-1fhbb51 span{color:blue;}</style>
```

Check it with [CodeSandbox live example](https://codesandbox.io/s/bold-brown-kz8x55?file=/src/App.tsx:116-220)

### Expected behavior 🤔

`sx` props should not be duplicated and no extra `style` items should be created. 

### Steps to reproduce 🕹

_No response_

### Context 🔦

_No response_

### Your environment 🌎

<details>
  <summary><code>npx @mui/envinfo</code></summary>

```
  System:
    OS: macOS 11.6.4
  Binaries:
    Node: 18.0.0 - /usr/local/bin/node
    Yarn: 1.22.19 - ~/.yarn/bin/yarn
    npm: 8.6.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 103.0.5060.114
    Edge: Not Found
    Firefox: 92.0
    Safari: 15.3
  npmPackages:
    @emotion/react: ^11.9.0 => 11.9.3 
    @emotion/styled: ^11.8.1 => 11.9.3 
    @mui/base:  5.0.0-alpha.87 
    @mui/icons-material: ^5.8.4 => 5.8.4 
    @mui/lab: ~5.0.0-alpha.84 => 5.0.0-alpha.88 
    @mui/material: ~5.8.2 => 5.8.6 
    @mui/private-theming:  5.8.6 
    @mui/styled-engine:  5.8.0 
    @mui/system:  5.8.6 
    @mui/types:  7.1.4 
    @mui/utils:  5.8.6 
    @mui/x-date-pickers:  5.0.0-alpha.1 
    @types/react: ^18.0.9 => 18.0.14 
    react: ^18.1.0 => 18.2.0 
    react-dom: ^18.1.0 => 18.2.0 
    typescript: ^4.7.3 => 4.7.4 
```
</details>



Issue discussion:
The problem seems to appear only in development mode. When you create a production version of the application, the styles aren't duplicated.
The Box should not forward the `sx` prop to the override component. This issue can be easily fixed by:
```diff
diff --git a/packages/mui-system/src/createBox.js b/packages/mui-system/src/createBox.js
index 60ef467b72..452d7d70da 100644
--- a/packages/mui-system/src/createBox.js
+++ b/packages/mui-system/src/createBox.js
@@ -11,7 +11,7 @@ export default function createBox(options = {}) {
     generateClassName,
     styleFunctionSx = defaultStyleFunctionSx,
   } = options;
-  const BoxRoot = styled('div')(styleFunctionSx);
+  const BoxRoot = styled('div', { shouldForwardProp: (prop) => prop !== 'sx' })(styleFunctionSx);
 
   const Box = React.forwardRef(function Box(inProps, ref) {
     const theme = useTheme(defaultTheme);
```
> Note that the `styled` use in `createBox` is from emotion or styled-components, not our wrapper. cc @mnajdova 
@siriwatknp  I would like to take the work on it.
@siriwatknp The issue can occur both in Box and Container. When I use the solution proposed above to Container, it seems to not work. Take the provided codesanbox for example, when I change Box to Container, the following styles and classname are recreated:

https://github.com/mui/material-ui/blob/4ced48effe6bca12e20d006e68fdd757f2ead72a/packages/mui-system/src/Container/createContainer.tsx#L77-L128
![QQ截图20220803110709](https://user-images.githubusercontent.com/85668115/182515593-1875c26a-bf9f-488f-b871-2c0ccf687f2a.png)

Can I create a PR only about Box?

> Can I create a PR only about Box?

Yep, this issue is just about the `Box`.

Solution patch:
diff --git a/packages/mui-system/src/createBox.js b/packages/mui-system/src/createBox.js
--- a/packages/mui-system/src/createBox.js
+++ b/packages/mui-system/src/createBox.js
@@ -11,7 +11,9 @@ export default function createBox(options = {}) {
     generateClassName,
     styleFunctionSx = defaultStyleFunctionSx,
   } = options;
-  const BoxRoot = styled('div')(styleFunctionSx);
+  const BoxRoot = styled('div', {
+    shouldForwardProp: (prop) => prop !== 'theme' && prop !== 'sx' && prop !== 'as',
+  })(styleFunctionSx);
 
   const Box = React.forwardRef(function Box(inProps, ref) {
     const theme = useTheme(defaultTheme);


Test patch:
diff --git a/packages/mui-system/src/createBox.test.js b/packages/mui-system/src/createBox.test.js
--- a/packages/mui-system/src/createBox.test.js
+++ b/packages/mui-system/src/createBox.test.js
@@ -1,5 +1,6 @@
 import * as React from 'react';
 import { expect } from 'chai';
+import { spy } from 'sinon';
 import { createRenderer } from 'test/utils';
 import { createBox, ThemeProvider } from '@mui/system';
 
@@ -54,4 +55,43 @@ describe('createBox', () => {
     const { container } = render(<Box />);
     expect(container.firstChild).to.have.class('Box');
   });
+
+  it('should accept sx prop', () => {
+    const Box = createBox();
+    const { container } = render(<Box sx={{ color: 'rgb(255, 0, 0)' }}>Content</Box>);
+    expect(container.firstChild).toHaveComputedStyle({ color: 'rgb(255, 0, 0)' });
+  });
+
+  it('should call styleFunctionSx once', () => {
+    const Box = createBox();
+    const spySx = spy();
+    render(<Box sx={spySx}>Content</Box>);
+    expect(spySx.callCount).to.equal(2); // React 18 renders twice in strict mode.
+  });
+
+  it('should still call styleFunctionSx once', () => {
+    const Box = createBox();
+    const spySx = spy();
+    render(
+      <Box component={Box} sx={spySx}>
+        Content
+      </Box>,
+    );
+    expect(spySx.callCount).to.equal(2); // React 18 renders twice in strict mode.
+  });
+
+  it('overridable via `component` prop', () => {
+    const Box = createBox();
+
+    const { container } = render(<Box component="span" />);
+    expect(container.firstChild).to.have.tagName('span');
+  });
+
+  it('should not have `as` and `theme` attribute spread to DOM', () => {
+    const Box = createBox();
+
+    const { container } = render(<Box component="span" />);
+    expect(container.firstChild).not.to.have.attribute('as');
+    expect(container.firstChild).not.to.have.attribute('theme');
+  });
 });