Search code examples
cssreactjsmaterial-uioverriding

Material UI Styled() - How to style Child components


Background

So I use the styled() utility function exposed by Material UI to style my components. Let's say I have a base component called Child and I import the base component into another React component. Now, if I am trying to style the imported component again, the styling will not override the base component styling. (But console.logs are called from within the styled() utility) Please see the example below:

import { styled } from "@mui/material";

function App() {
  const StyledChild = styled(Child)(({ theme }) => {
    console.log("called from App");

    return {
      backgroundColor: "black"
    };
  });

  return <StyledChild />;
}

function Child() {
  const Div = styled("div")(({ theme }) => {
    console.log("called from Child");

    return {
      backgroundColor: "red"
    };
  });

  return <Div>hello world</Div>;
}

export default App;

console results in the following:

called from App

called from Child

codesandbox

Issue

As mentioned earlier, and can be seen in the codesandbox example, only the base styling of backgroundColor: 'red' is applied. The imported component's styling of backgroundColor: 'black' is not applied, even though called from App is logged.

Question

  • How would one effectively style a component that has been previously styled?
  • And (just curious) how come the above solution does not work, shouldn't if the styled() utility is called, then the styling should be applied by what was defined in the returned obj?

Edit/Update

Upon experimenting, I see that even if I remove the original style of Child, the styling at the parent level still cannot be rendered.

import { styled } from "@mui/material";

function App() {
  const StyledChild = styled(Child)(({ theme }) => {
    console.log("called from App");

    return {
      backgroundColor: "black"
    };
  });

  return <StyledChild />;
}

function Child() {

  return <div>hello world</div>;
}

export default App;

The result is not affected by the backgroundColor: "black" at the parent level, hence changing the title of the question to fit the issue better. How does one style a child component at the parent level?


Solution

  • After a couple of days of attempting to isolate the issue, I was able to find the cause of the issue and a viable solution. Hopefully, if anyone in the future runs into a similar issue, they can resolve it with the following.

    So the original problem was that the parent's styling did not affect the child. The issue was that in the child component, I did not include the following: function Child({ ...others }) { //function component and inside the component itself, I need to add the {...others} as one of the attributes of the element. See full solution:

    import { styled } from "@mui/material";
    
    function App() {
      const StyledChild = styled(Child)(({ theme }) => {
        console.log("called from App");
    
        return {
          backgroundColor: "black"
        };
      });
    
      return <StyledChild />;
    }
    
    function Child({ ...others }) {
      const Div = styled("div")(({ theme }) => {
        console.log("called from Child");
    
        return {
          backgroundColor: "red"
        };
      });
    
      return <Div { ...others }>hello world</Div>;
    }
    
    export default App;
    
    

    My best bet is that the parent styling is applied via classes under the hood (if anyone has documentation links, that would be greatly appreciated). And those classes need to be applied as attributes of the Child element.

    codesandbox solution