Adjust the color based on the value using JavaScript

I have a React component where I need to change the text color based on the value passed as props. Here is my code:



const ProductCard = (props) => {
    const classes = useStyles();

    useEffect(() => {
        const category = document.getElementById('category');

        if(props.category === "youtube"){
            category.style.color="#DC143C";
        }
        if(props.category === "blog"){
            category.style.color="#00FFFF";
        }
        if(props.category === "instagram"){
           category.style.color="#FF88FF";
        }
        if(props.category === "twitter"){
            category.style.color="#3366FF";
        }
    }, []);

    return (
        <Card className={classes.root}>
            <CardContent className={classes.content}>
                <Typography id="category" className={classes.category} component="p">
                    {props.category}
                </Typography>
            </CardContent>
        </Card>
    )
}

export default ProductCard

Although this code partially works, only the first element's color gets changed, not the others. What could be causing this issue?

Answer №1

Your current code is designed to only execute when the component mounts with an empty array dependency, meaning that any changes to props will not be reflected. This could be the root cause of the issue you're facing.

It might be beneficial to simplify your code by avoiding direct manipulation of the DOM. One alternative approach could be to create a dictionary to apply styles to your elements, like demonstrated below:


    const colorPalette = {
      youtube: "#DC143C", 
      blog: "#00FFFF", 
      instagram: "#FF88FF", 
      twitter: "#3366FF", 
    }

    const ProductCard = ({ category }) => {
      const classes = useStyles();
  
      return (
          <Card className={classes.root}>
              <CardContent className={classes.content}>
                  <Typography id="category" style={{ color: colorPalette[category] }} className={classes.category} component="p">
                      {category}
                  </Typography>
              </CardContent>
          </Card>
      )
  }
  
  export default ProductCard

Answer №2

It is recommended to refrain from querying the DOM within a React application. Instead, consider creating state to manage classes or styles and passing them to components.

Additionally, removing an empty array from useEffect may improve performance and functionality.

Answer №3

When you use getElementById to select an element, it will only return one element.

const category = document.getElementById('category'); // this line here

This is because IDs are meant to be unique. There should only be one element with the ID category on the page. So when you modify the style of container, only that specific element gets affected.

Furthermore, IDs are not restricted to a particular component scope. Therefore, if there are multiple instances of the ProductCard component, calling getElementById will always refer to the category of the first ProductCard component.

Possible Solutions

These solutions may vary based on your components and setup, but at least one of them should work for your case.

Utilize a color prop

If your Typography component supports a color or style prop, utilize that instead. By doing so, you are explicitly specifying the color for a specific component in React.

const colors = {
    youtube: "#DC143C", 
    blog: "#00FFFF", 
    instagram: "#FF88FF", 
    twitter: "#3366FF", 
}

const ProductCard = (props) => {
    const classes = useStyles();

    return (
        <Card className={classes.root}>
            <CardContent className={classes.content}>
                <Typography id="category" className={classes.category} component="p" style={{ color: colors[props.category] }}>
                    {props.category}
                </Typography>
            </CardContent>
        </Card>
    )
}

export default ProductCard

Introduce a wrapper component

You might consider enclosing just the typography element within a div and setting the text color through this approach. Although not the most optimal solution, it can still serve the purpose.

const colors = {
    youtube: "#DC143C", 
    blog: "#00FFFF", 
    instagram: "#FF88FF", 
    twitter: "#3366FF", 
}

const ProductCard = (props) => {
    const classes = useStyles();

    return (
        <Card className={classes.root}>
            <CardContent className={classes.content}>
                <div style={{ color: colors[props.category] }}>
                    <Typography id="category" className={classes.category} component="p" style={{ color: colors[props.category] }}>
                        {props.category}
                    </Typography>
                </div>
            </CardContent>
        </Card>
    )
}

export default ProductCard

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

A step-by-step guide on retrieving a value from a DateTime picker in a React application

I am utilizing Material-UI to create a DateTime picker. You can check out my demo code here. In order to observe the current selected value, I have added console.log to the function handleChange. However, I am facing an issue where the value does not chan ...

Encountering a Stripe Axios error code due to a faulty response while sending a post

Looking for assistance with the backend code for the payment gateway. I need help testing if I am receiving any response. const router = require("express").Router(); const stripe = require("stripe")(process.env.STRIPE_KEY); router.post( ...

Struggling with a CSS problem involving the UL > LI > LI structure

Currently facing a challenge with the CSS on my website's main navigation menu. The drop-down for menu items with child pages should have solid color, no border, round corners on the bottom, and a drop shadow. I've almost got it right, but for ...

prompting the JavaScript hangman game to identify the letters in the "selected word"

Currently, I am on a mission to teach myself Javascript and have taken on the challenge of creating a simple hangman game. This type of project is commonly used in interviews or tests, so it seemed like a great opportunity for practice. My approach involve ...

Maintaining the integrity of a list within a for loop

I have a challenge where I need to display 3 elements in cards on each row from a list of elements. The issue with my current code is that it only displays the first two elements and then the loop stops. Here is the code snippet using ReactJS and Materia ...

Issue with creating req.session in Node.js client-sessions library

Encountering troubles with node-client-sessions, I decided to test out a sample application found at https://github.com/fmarier/node-client-sessions-sample. Despite the simplicity of this app, I am consistently faced with an error: TypeError: Cannot read p ...

What is the best way to use a computed property as a style value for a component in Vue.js?

My component's template includes the following HTML element: .grid-item(:style="{ width: columnWidth, backgroundColor: 'blue' }") I want to dynamically set the width of this element using a computed property: computed: { columnWidth () ...

When hovering over one item, it causes a hover effect on an item in a SEPARATE container

My goal is to create a unique interaction between links and images, where hovering over a link will transform the corresponding image below it, and vice versa. I have been searching for solutions but have only found methods that work when all items are wit ...

problem of keeping behat/selenium browser open after execution

I am attempting to execute the behat/selenium test with Chrome browser by running the following feature scenario. I would like to keep the browser window open instead of closing the Chrome immediately. Even though I have implemented the iWaitForSeconds ste ...

When the mouse is clicked, rotate the object along its axis using OBJ Loader in THREE.js

I am looking to add a feature where my object rotates on its axis when the mouse is dragged. The challenge I am facing is that I can only access my skull object within the function, which limits where I can place a rotation increment inside render(). Coul ...

Tips on incorporating a callback function within the setState function

I've encountered a problem with my click handler. Initially, it was working fine like this: handleClick = () => { const { isCalendarOpen } = this.state; this.setState ({ isCalendarOpen: !isCalendarOpen }); ...

Issue with Yup and Formik not validating checkboxes as expected

I'm struggling to figure out why the validation isn't functioning as expected: export default function Check() { const label = { inputProps: { "aria-label": "termsOfService" } }; const formSchema = yup.object().shape({ ...

AngularJS routing with html5mode causing 404 error when using htaccess

I am currently working on my very first angularjs application using version 1.6x, and I am encountering some 404 errors with my router. Here is how my router is set up: app.config(function($routeProvider, $locationProvider) { $locationProvider.html5M ...

Expanding a Landy react app to smoothly transition to a different page with the Router model

I am seeking assistance in updating the Landy out of the box application from https://github.com/Adrinlol/landy-react-template In a standard React/Javascript model, I would typically write code like the following: <Route path='/thanks' exact ...

Angular components are not properly adhering to the specified height and width dimensions for child elements

I seem to be having trouble applying height/width to a child component in angular. Can someone take a look and point out where I may have gone wrong? app.component.html <app-child [width]="10" [height]="10"></app-child> .child.ts import { C ...

Annoying div unexpectedly wrapping content after using appendTo

Greetings, esteemed members of the SO community, I am here once again with a question that requires your assistance. Context: I am currently working on a grid system that allows users to drag and drop items onto specific grid fields. When the grid is re ...

The Vue.js 2 router is exclusively pulling components from the navigation bar, rather than directly from the URL

After selecting a page from the menu, the correct component loads. However, directly accessing the page URL does not display the content. This is the main template (which contains the menu): <template> <div class="row"> <div cl ...

Is it possible to replace Material UI theme with a custom JSS theme?

Currently, I am utilizing JSS themes for styling my components. However, it appears that my personalized JSS theme is conflicting with the JSS theme applied to the Material UI components. The version of material-ui being used is 1.0.0-beta.22. The setup r ...

Angular - No redirection occurs with a 303 response

Having an issue with redirection after receiving a 303 response from a backend API endpoint, which includes a Location URL to any subpage on my site. Upon attempting the redirect, an error is triggered: Error: SyntaxError: Unexpected token '<&ap ...

css malfunctioning user interface

I'm struggling to figure out how to design a CSS toolbar. My goal is to create a 22x22 button toolbar with 4 buttons. I have this PNG image: and the following code: <style> #nav {background: url(content/images/crtoolbar.png) no-repeat;height: ...