Using inline CSS to apply conditional styles to a component in React is a great way to customize the

I'm currently working on customizing the styles of some buttons depending on their 'active' status and whether the user is hovering over them. So far, it's partially working but I'm encountering behavior that I can't fully comprehend.

How can I implement conditional styling for a component based on its state and user interaction?

For reference, I have set up an example in this SANDBOX

Here is the primary JS file excerpt:

demo.js

import React from "react";
import PropTypes from "prop-types";
//import { makeStyles } from "@material-ui/core/styles";
import { withStyles } from "@material-ui/styles";
import { Button } from "@material-ui/core";

const useStyles = theme => ({
  root: {
    backgroundColor: theme.palette.secondary.paper,
    width: 500
  },
  pageButton: {
    backgroundColor: "black",
    color: "blue",
    width: 30,
    minWidth: 20,
    "&:hover": {
      backgroundColor: "green"
    }
  },
  normalButton: {
    width: 30,
    minWidth: 20,
    backgroundColour: "red"
  }
});

class Feature extends React.Component {
  constructor(props) {
    super(props);
    this.state = { currentPage: 0 };
  }
  handleClick(page) {
    this.setState({ currentPage: page });
  }

  fetchPageNumbers() {
    return [1, 2, 3];
  }
  render() {
    const classes = this.props.classes;
    return (
      <div className={classes.root}>
        {this.fetchPageNumbers().map((page, index) => {
          return (
            <div>
              <Button
                onClick={() => this.handleClick(page)}
                key={page}
                className={
                  this.state.currentPage === page
                    ? classes.pageButton
                    : classes.normalbutton
                }
              >
                {page}
              </Button>

              <Button
                onClick={() => {}}
                key={page * 20}
                className={classes.normalButton}
              >
                {page * 20}
              </Button>
            </div>
          );
        })}
      </div>
    );
  }
}

Feature.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(useStyles)(Feature);

The issue lies in how the first row of buttons reacts. The second row applies the styles correctly. However, the first row only reflects changes when a button is clicked. What I aim to achieve is setting the state based on whether the current button is active (i.e., state == buttonNumber), and also accounting for user hover interactions across all buttons.

Answer №1

How can I dynamically apply styles to a component based on its state and user behavior?


Implementing conditional styles for user behavior

If you want to apply styles when the component is being hovered over, you can use the following CSS:

"&:hover": {
  // Hover styles
}

Applying conditional styles based on component parameters (props)

Unfortunately, makeStyles does not have direct access to the props passed to a component.


However, there are ways to work around this limitation.

1. Using injectSheet HOC

It's important to note that the useStyles function in your code is not actually a hook.

const styles = props => ({
  root: {
    width: props.size === 'big' ? '100px' : '20px'
  }
})

or

const styles = {
  root: {
    width: props => props.size === 'big' ? '100px' : '20px'
  }
}

Then, use it like this:

const CustomComponent = ({size, classes}) => <Component className={classes.root} />;

export default withStyles(styles)(CustomComponent);

2. Utilizing style hooks with parameters (for functional components)

import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles(theme => ({
  root: {
    width: props => props .size === "big" ? "100px" : "20px"
  }
}));

const classes = useStyles();

Alternatively, you can do:

import { makeStyles } from "@material-ui/core/styles";
const useStyles = params =>
  makeStyles(theme => ({
    root: {
      width: params.size === "big" ? "100px" : "20px"
    }
  }));

const classes = useStyles(whateverParamsYouWant)();

Answer №2

Responding to @keikai, it is also possible to provide an object as an argument to the styles() hook instead of just passing props which was causing an error in my case.

import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles(theme => ({
  root: {
    width: ({ size }) => (size === "big" ? "100px" : "20px")
  }
}));

const classes = useStyles({ size });

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

Checking the types of arrays does not function properly within nested objects

let example: number[] = [1, 2, 3, 'a'] // this code block correctly fails due to an incorrect value type let example2 = { demo: 1, items: <number[]> ['a', 'b'], // this code block also correctly fails because of ...

Learn how to iterate over an array and display items with a specific class when clicked using jQuery

I have an array with values that I want to display one by one on the screen when the background div is clicked. However, I also want each element to fade out when clicked and then a new element to appear. Currently, the elements are being produced but th ...

This error is thrown when trying to access the property 'message' of an undefined value

I'm currently working on adding an AJAX contact form to my website. However, I've run into a problem where when I try to submit the form, I encounter the following error in Google Chrome: "Uncaught TypeError: Cannot read property 'message&a ...

The completion event was not triggered during the AJAX request

I am having an issue with a function that I have created to make an ajax call. Despite using the .done method, it does not seem to be firing as expected. Upon checking my console for errors, I came across the following message: function getIncidentInfo( ...

Selecting the optimal data structure: weighing the benefits of using boolean check versus array .include (balancing performance and redundancy

My objects can have one or more properties assigned, with a total of 5 different properties in my case. To illustrate this, let's use a simple movie example where each movie can be assigned from 5 different genres. I have come up with two methods to ...

Develop a dynamic thunk and additional reducer to efficiently handle multiple API calls and retrieve data

Using Redux and Redux-Toolkit, I aim to streamline my code by implementing a single asynchronous Thunk and extra reducer for multiple requests. Below is the setup for both the company and client slices: import { createSlice, createAsyncThunk } from &apos ...

Error: Uncaught object in AngularJS ngRoute

I keep encountering an uncaught object error in my browser console while trying to load my AngularJS application. I am unsure if this issue is related to ng-route.js or if it's something else, as the error message only says 'uncaught object' ...

Issue with deploying production build in Next.js causing 404 errors on sub pages

After deploying my Next.js build code to production using the command next export -o outDir, I noticed that only the home page is working. When attempting to access /login, I am receiving a 404 error. Can anyone offer guidance on how to resolve this issu ...

Have the quotes within my markup been replaced with HTML entities?

Currently, I am working on a content page that uses a master page which includes a text box and a button. My goal is to have the button execute some JavaScript code before performing any other actions. At the moment, I am in the testing phase of this JavaS ...

Steps to align text below an icon in the bottom navigation bar within a scaffold:

I am currently designing an application using Jetpack Compose, and I'm facing a challenge with placing text at the bottom of the navigation bar. Here is how it appears: My objective: Scaffold @Composable fun StandardScaffold( navController: Nav ...

Difficulty in preventing the website from reloading when accessing tabs

I am working on a function that allows users to access the content of a tab without causing the page to reload. Initially, I tried using something like $( "#tab1" ).click(function() { $("#content").load("tab1.html #content > *"); }); but unfortun ...

Safari failing to show SVG at correct alignment

I am looking to implement a unique feature on my website where image placeholders are displayed for 1 second before fading out to reveal the actual image. These image containers will be responsive, adjusting to fit the size of their parent container. In a ...

What is the impact of memory on NodeJS performance?

Currently delving into a book on NodeJS, I stumbled upon an intriguing example: const express = require('express') const bodyParser = require('body-parser') const app = express() var tweets = [] app.listen('8000', '172 ...

Ways to determine if a user is using a PC using JavaScript

I am developing a website using node.js that will also serve as the foundation for a mobile app. The idea is to have users access the website on their phones and use it like an app. But I want to implement a feature that detects when the site is being vi ...

Troubleshooting issue: Click function not responding inside Bootstrap modal

Below is the JavaScript code for my click function $(".addPizza").on("click", function(event) { event.preventDefault(); console.log("hello") let userId = $("#userId").attr("data-id"); let pizzaRecipe = $('#pizza-recipe').val().trim(); ...

Adjusting the minimum value on a textfield with JQuery Validate plugin in real-time

I am attempting to dynamically update the minimum value on one field based on input from other fields. Here is a brief overview of my code: $("#new_project").on("click", function() { switch($('input:radio[name=quality-level]:checked').val() ...

Step by step guide on creating a CSS triangle shape in front of a span element

Can you help me troubleshoot why my css triangle isn't displaying before my span? I've tried everything but it just won't show up. .triangle:before { width: 0; height: 0; border-top: 3px solid transparent; border-right: 6px solid ...

The Ajax Form disappears from the page

After racking my brain for a while, I've come to the conclusion that it's time to seek some assistance. I have work tomorrow and I don't want to spend all night on this. The issue lies in my form which is located inside a modal, here is my ...

"Enhabling tablesorter pagination to ensure that buttons always stay in sync with

I am experiencing an issue with the pagination buttons staying at the bottom of my page, even when there are only 2 entries left on the last page. Check out my table here: Is there a way to make the pagination buttons dynamically move to the top based on ...

Challenges with registering on Ajax platform

I'm currently facing an issue with my login/sign up process and I can't seem to figure it out. I have shared a jsfiddle link with the code, but I am struggling to identify the problem. https://jsfiddle.net/Zemanor/fuzrkw16/1/ Whenever I submit ...