Enabling customized styling for a React component using props with the withStyles API: A step-by-step guide

In an effort to enhance our React application with MaterialUI, I am developing a simple reusable component.

One challenge I'm facing is the need to allow for different styles of this reusable component to be customized through props by the consuming component.

Here's a snippet of the code:

import { withStyles } from '@material-ui/core';

const styles = theme => ({
image: {
    maxHeight: '200px'
}
});

render() {
        const classes = this.props.classes
        return (
            <div>
                 ...
                 <img className={classes.image} src={this.state.filePreviewSrc} alt="" />
                 ...
            </div>
        );
    }

Suppose I want to enable developers to customize the appearance of classes.image. Is there a way to override the hard-coded image class?

Is utilizing the withStyles API the appropriate method for creating components which can have their appearance tailored by the consuming component/developer?

Answer №1

There are several methods to customize styles in React components:

  1. Utilize props within the styles
  2. Use props to determine when specific classes should be applied
  3. Implement customization using withStyles

When choosing option 3, the styles of the wrapping component will be combined with the original styles, but the CSS classes of the wrapping component will take precedence as they appear later in the <head>.

Here's an example showcasing all three customization approaches:

NewComponent.js

import React from "react";
import { withStyles } from "@material-ui/core/styles";

const styles = {
  root: props => ({
    backgroundColor: props.rootBackgroundColor
      ? props.rootBackgroundColor
      : "green"
  }),
  inner: props => ({
    backgroundColor: props.innerBackgroundColor
      ? props.innerBackgroundColor
      : "red"
  })
};

const NewComponent = ({ classes, children, hideInnerDiv = false }) => {
  return (
    <div className={classes.root}>
      Outer div
      {hideInnerDiv && <div>{children}</div>}
      {!hideInnerDiv && (
        <div className={classes.inner}>
          Inner div
          <div>{children}</div>
        </div>
      )}
    </div>
  );
};
export default withStyles(styles)(NewComponent);

index.js

import React from "react";
import ReactDOM from "react-dom";
import { withStyles } from "@material-ui/core/styles";

import NewComponent from "./NewComponent";

const styles1 = theme => ({
  root: {
    backgroundColor: "lightblue",
    margin: theme.spacing(2)
  },
  inner: {
    minHeight: 100,
    backgroundColor: "yellow"
  }
});
const Customization1 = withStyles(styles1)(NewComponent);

const styles2 = {
  inner: {
    backgroundColor: "purple",
    color: "white"
  }
};
const Customization2 = withStyles(styles2)(NewComponent);

function App() {
  return (
    <div className="App">
      <NewComponent>Not customized</NewComponent>
      <Customization1>Customized via withStyles 1</Customization1>
      <Customization2>Customized via withStyles 2</Customization2>
      <NewComponent rootBackgroundColor="lightgrey" hideInnerDiv>
        Customized using props
      </NewComponent>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

https://codesandbox.io/s/styling-reusable-component-5zwis?fontsize=14

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to retrieve button value with material-ui package

My task requires me to retrieve the value of a button, as it contains an ID essential for further steps. Initially, I used a standard button with Bootstrap styling and everything functioned correctly. <button value={row.vacationRequestID} c ...

The mergeStyles function is unable to target a child element by its id within a parent element identified by its class

Consider the code snippet below: <div class="example"> <div id="label"> Label text </div> </div> The CSS provided can style 'Label text' successfully: .example #label { color: red; } However ...

Initiate movement upon scrolling

I would like to activate this box animation once the user scrolls down by adding a class. I'm having trouble getting this to work, it seems like I might be missing something crucial. Here is my current code, can someone point out where I am going wro ...

Using JQuery to trigger CSS3 animations on one element when clicking on another

My Rails app has a feature similar to reddit where users can upvote or downvote content. I'm currently working on creating a CSS3 animation that triggers when a user clicks the downvote button. Here's how I'm using JQuery: <div class="a ...

The useEffect React Hook is missing a dependency: 'fetchTracker'. Please make sure to add it to the dependency array or consider removing it

I recently encountered a challenging issue with one of my projects. The file in question is responsible for tracking data, which is then displayed on a map within an application. Despite my attempts to find a solution on StackOverflow, I have not found an ...

Deactivate a portion of a website's CSS through coding strategies

Is it feasible to create a file that automatically disables certain parts of a website's CSS? Specifically, I would like to disable the following when visiting the site: Is there a method to achieve this? ...

Running `npm start` encountered an issue: `npm ERR! code ELIFECYCLE`

Having an issue with starting the app using 'npm start'. After creating a folder for react files and running the command, I encounter: npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! <a href="/cdn-cgi/l/email-protection" class="__cf_email__ ...

A div element that automatically adjusts its width to fill the available horizontal space, and is then re

div</code> elements next to each other horizontally. The right div should adjust its size based on its content up to a set maximum width, while the left one should occupy the remaining space. I have successfully achieved this layout by floating the ...

Unable to display specific data in Drop Down using AngularJS

I've encountered an issue with my dropdown menu not displaying data when I select the appropriate option. There are two choices available. CSHTML <ui-select ng-model="ctrl.requestType" theme="selectize" title="Choose type of requisition" style="m ...

triggering php object on mouse hover

I'm currently working on creating a mouseover effect for my PHP elements within a store. My goal is to have a transparent div appear over the dynamically generated PHP sections. I have set it to display block mode to test its functionality and positio ...

Looking for an effective method to implement CSS styling within a list cell in JavaFX?

As a beginner in JavaFX with limited knowledge of CSS, I struggled to conduct proper research and provide relevant information here. I apologize for any confusion or duplication. I am seeking a solution to apply CSS to JavaFX controls, specifically in a Li ...

Encountering an issue with the creation of dynamic pages in Next.JS where an Error 404 message is displayed instead

I recently started delving into Next.JS and decided to implement getStaticPaths() in a practical example. However, when I attempted to apply it using my own data instead of the examples from JSONPlaceholder, I encountered a frustrating 404 error without an ...

Attempting to solve the issue of passing props from the parent `<Tabs>` component to the child `<ToggleButton>` component is proving to be quite challenging in my opinion. I believe the

How can I prevent specific props from being passed down from the parent component (<Tabs) to the child component (<ToggleButton)? I needed to use the functions of <Tabs along with toggle buttons, so I combined them. Please note that I am using th ...

The background colors are not extending to the full width of the screen

I am facing an issue in my CSS code while trying to create a footer. The background color is not filling the width of the screen, and I had encountered the same problem earlier. Here is how it looks: (https://i.sstatic.net/5VxYU.png) HTML Code: *{ ma ...

Expand row size in grid for certain row and item

For my project, I am utilizing a Grid layout to display 5 items per row. https://i.sstatic.net/PW6Gu.png Upon clicking on an item, my goal is to have the item detail enlarge by increasing the size of the HTML element. https://i.sstatic.net/nGj8l.png Is t ...

Creating evenly spaced columns within a structure

Is there a way to create 3 equal columns in HTML5 without using tables? I'm having trouble achieving the desired result: https://i.sstatic.net/AJIA3.png The issue is that one of the columns doesn't look like the other two, even though they all ...

Utilizing the smallslider feature through jQuery/JavaScript operations

I've recently embarked on the journey of learning JavaScript/jQuery. I've been attempting to incorporate this cool effect, but unfortunately, I'm facing some difficulties with it: My goal is to understand how to execute this effect using Ja ...

Issue with Bootstrap 4.2 modal: Unable to edit input fields, button cannot be clicked, modal does not close

https://i.sstatic.net/vHnVG.png https://i.sstatic.net/MhU3f.png Utilizing Bootstrap 4.2.1, I have a modal that opens via a specific link: <a href="#" data-toggle="modal" data-target="#inviteByEmailPopup" data-backdrop="false" data-keyboard="false"> ...

typescript-react-router-dom common errors

I am experiencing a typescript error related to Switch and Route from react-router-dom, and I am unsure of the cause. It is possible that there is an incompatibility issue with library versions, but I have been unable to find any information on this. Swit ...

The children elements inside a parent div with Flexbox are now taking on the height of their container

I am facing an issue with my flexbox grid layout where one column contains a tall image while another column has two shorter images stacked on top of each other. The problem arises when viewing the layout in Internet Explorer, as the height of the smaller ...