最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to set a css property (background-color) dynamically in React? - Stack Overflow

programmeradmin4浏览0评论

I have a slideshow based on an array of objects with its characteristics, one of them is the background-color of the current slide. I have a property called bg which stores it. This is what I am using to set each background-color, which changes to every image, however I am using an inline style to do that.

I'd like to know if there is a way to do that without using this inline style?

Here is a sample of my code:

import React from 'react'
import { Fragment } from 'react'

import classes from './MainPageHeader.module.css'

const MainPageHeader = props => {

    let [minorSlideImg, setMinorSlideImg] = React.useState(0)

    let minorSlides = [
        {
            img: require('../../../assets/images/Header/MinorSlider/imgSolo1-mainpage.png'),
            alt: 'Produto 1',
            linkText: ['PRODUTO 5', '$ 19.99'],
            productId: 5,
            bg: 'rgb(151, 105, 105)'
        },
        {
            img: require('../../../assets/images/Header/MinorSlider/imgSolo2-mainpage.png'),
            alt: 'Produto 2',
            linkText: ['PRODUTO 13', '$ 199.99'],
            productId: 13,
            bg: '#fad3e0'
        },
        {
            img: require('../../../assets/images/Header/MinorSlider/imgSolo3-mainpage.png'),
            alt: 'Produto 3',
            linkText: ['PRODUTO 10', '$ 499.99'],
            productId: 10,
            bg: '#ccc'
        },
        {
            img: require('../../../assets/images/Header/MinorSlider/imgSolo4-mainpage.png'),
            alt: 'Produto 4',
            linkText: ['PRODUTO 11', '$ 999.99'],
            productId: 11,
            bg: 'rgb(238, 225, 183)'
        },
    ]
    
    const passSlideHandler = () => {
        if (minorSlideImg < minorSlides.length - 1) {
            setMinorSlideImg(minorSlideImg + 1)
        } else {
            setMinorSlideImg(0)
        }
    }   
    
    React.useEffect(() => {
        const interval = setTimeout(() => {
            passSlideHandler()
        }, 5000);
        return () => clearTimeout(interval);
    });    


    return (
        <Fragment>
            <div 
                className={classes.MinorSlider_subContainer} 
                style={{backgroundColor: minorSlides[minorSlideImg].bg}} // <= This is what I'd like to remove
            >
                <img 
                    src={minorSlides[minorSlideImg].img}
                    alt={"img-1"} 
                />
            </div>
        </Fragment>
    )
}

export default MainPageHeader

CSS:

.MinorSlider_subContainer {
    height: 65%;
    width: 50%;
    background-color: #ccc;
}

.MinorSlider_subContainer img {
    max-width: 100%;
}

.MinorSlider_subContainer div {
    position: relative;
    background-color: white;
    width: 100%;
    height: 65px;
}

.MinorSlider_subContainer div > *{
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;

    width: 100%;
    height: 100%;
    padding-left: 25px;
    text-decoration: none;
}

.MinorSlider_subContainer div p {
    margin: 0;
    color: rgb(75, 75, 75);
}

As can be seen, every five seconds the index of minorSlides changes, therefore, the slide that is being shown changes as well. This index is used to refer to each feature of the current slide.

So, is there a way to remove this inline style and make my JSX cleaner?

If I was using HTML, CSS and JS I could do that with JQuery or even plain JS, but I don't know how to do that here. I know I could create the element with a loop, but I'd like to keep changing only the index and not the whole element.

Here is the sildeshow:

I have a slideshow based on an array of objects with its characteristics, one of them is the background-color of the current slide. I have a property called bg which stores it. This is what I am using to set each background-color, which changes to every image, however I am using an inline style to do that.

I'd like to know if there is a way to do that without using this inline style?

Here is a sample of my code:

import React from 'react'
import { Fragment } from 'react'

import classes from './MainPageHeader.module.css'

const MainPageHeader = props => {

    let [minorSlideImg, setMinorSlideImg] = React.useState(0)

    let minorSlides = [
        {
            img: require('../../../assets/images/Header/MinorSlider/imgSolo1-mainpage.png'),
            alt: 'Produto 1',
            linkText: ['PRODUTO 5', '$ 19.99'],
            productId: 5,
            bg: 'rgb(151, 105, 105)'
        },
        {
            img: require('../../../assets/images/Header/MinorSlider/imgSolo2-mainpage.png'),
            alt: 'Produto 2',
            linkText: ['PRODUTO 13', '$ 199.99'],
            productId: 13,
            bg: '#fad3e0'
        },
        {
            img: require('../../../assets/images/Header/MinorSlider/imgSolo3-mainpage.png'),
            alt: 'Produto 3',
            linkText: ['PRODUTO 10', '$ 499.99'],
            productId: 10,
            bg: '#ccc'
        },
        {
            img: require('../../../assets/images/Header/MinorSlider/imgSolo4-mainpage.png'),
            alt: 'Produto 4',
            linkText: ['PRODUTO 11', '$ 999.99'],
            productId: 11,
            bg: 'rgb(238, 225, 183)'
        },
    ]
    
    const passSlideHandler = () => {
        if (minorSlideImg < minorSlides.length - 1) {
            setMinorSlideImg(minorSlideImg + 1)
        } else {
            setMinorSlideImg(0)
        }
    }   
    
    React.useEffect(() => {
        const interval = setTimeout(() => {
            passSlideHandler()
        }, 5000);
        return () => clearTimeout(interval);
    });    


    return (
        <Fragment>
            <div 
                className={classes.MinorSlider_subContainer} 
                style={{backgroundColor: minorSlides[minorSlideImg].bg}} // <= This is what I'd like to remove
            >
                <img 
                    src={minorSlides[minorSlideImg].img}
                    alt={"img-1"} 
                />
            </div>
        </Fragment>
    )
}

export default MainPageHeader

CSS:

.MinorSlider_subContainer {
    height: 65%;
    width: 50%;
    background-color: #ccc;
}

.MinorSlider_subContainer img {
    max-width: 100%;
}

.MinorSlider_subContainer div {
    position: relative;
    background-color: white;
    width: 100%;
    height: 65px;
}

.MinorSlider_subContainer div > *{
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;

    width: 100%;
    height: 100%;
    padding-left: 25px;
    text-decoration: none;
}

.MinorSlider_subContainer div p {
    margin: 0;
    color: rgb(75, 75, 75);
}

As can be seen, every five seconds the index of minorSlides changes, therefore, the slide that is being shown changes as well. This index is used to refer to each feature of the current slide.

So, is there a way to remove this inline style and make my JSX cleaner?

If I was using HTML, CSS and JS I could do that with JQuery or even plain JS, but I don't know how to do that here. I know I could create the element with a loop, but I'd like to keep changing only the index and not the whole element.

Here is the sildeshow:

Share Improve this question edited Dec 13, 2020 at 17:42 lissettdm 13.1k1 gold badge23 silver badges42 bronze badges asked Dec 13, 2020 at 15:21 Berg_DurdenBerg_Durden 1,7796 gold badges33 silver badges63 bronze badges 7
  • Could you share a picture or short video of your current output? – Rojo Commented Dec 13, 2020 at 15:24
  • @Rojo I inserted a GIF. I changed the interval to 1500 to make the GIF shorter. – Berg_Durden Commented Dec 13, 2020 at 15:35
  • So what is the problem with using inline? – Rojo Commented Dec 13, 2020 at 15:38
  • No problem. I'd just like to make the JSX cleaner. – Berg_Durden Commented Dec 13, 2020 at 15:43
  • If you want to remove the inline style you can create a css class for every color, and instead of setting the style you can set the className value, or are you getting this data dynamically? – lissettdm Commented Dec 13, 2020 at 15:44
 |  Show 2 more ments

3 Answers 3

Reset to default 2

If you can't create a css class for every color, the other option is to add the style tag and override the background-color property:

const subcontainerBackground = `.${classes.MinorSlider_subContainer} { background-color: ${minorSlides[minorSlideImg].bg}}`
        
return {(
   <Fragment>
      <style>
        {subcontainerBackground}
      </style>
      <div className={classes.MinorSlider_subContainer} >
         //....
      </div>
    </Fragment>
}

EDIT

Also you can add the style tag using Document.createElement():

  useEffect(() => {
    const content = `.${classes.MinorSlider_subContainer} { background-color: ${minorSlides[minorSlideImg].bg}}`;
    const style = document.createElement("style");
    style.innerHTML = content;
    document.head.appendChild(style);

    return () => document.head.removeChild(style);
  }, [minorSlideImg]);

Well it should be alright to use inline styling in this case.

Additionally you can do something like:

{
  ...
  bgClass: 'red'
}

add that class to the div element:

<div className={`classes.MinorSlider_subContainer ${minorSlides[minorSlideImg].bgClass}`} />

and style it in the end:

.red {
  background: 'red';
}

Or you can try to use reference

const ref = useRef()

useEffect(() => {
  if (ref.current == null) {
    return
  }

  ref.current.style.backgroundColor = minorSlides[minorSlideImg].bg
}, [minorSlideImg, ref])

<div ref={ref} />

Here is my solutions for the same. Except, I add the colours in a list and use the rand function.

Here is the colour list

 const color_list = [
    "tomato",
    "blueviolet",
    "cornflowerblue",
    "indianred",
    "MediumAquaMarine",
    "MediumPurple",
    "Rebeccapurple",
    "sandybrown",
    "seagreen",
    "palevioletred",
    "lightsteelblue",
    "Gold",
    "teal",
  ];

I create a variable and add random function to it, to select a bunch of colours.

const rando_color = color_list[Math.floor(Math.random() * color_list.length)];

Simply pass the variable in the style option in the html div tag to dynamically assign background color

<div
   p={4}
   style={{
   backgroundColor: rando_color, // Added variable here 
   fontFamily: "Oswald",
   border: "solid 2px white",
   }}
   >
<h1>Some Content</h1>
  </div>

To make it simple, just add the variable directly in the tag without any curly braces. Also you could try using this variable in a react state for better loading. Add a default prop as well.

发布评论

评论列表(0)

  1. 暂无评论