Как динамически установить свойство css (background-color) в React?

#javascript #css #reactjs #loops #jsx

#javascript #css #reactjs #циклы #jsx

Вопрос:

У меня есть слайд-шоу, основанное на массиве объектов с его характеристиками, один из которых является background-color текущим слайдом. У меня есть свойство, bg которое его хранит. Это то, что я использую для установки каждого цвета фона, который изменяется для каждого изображения, однако я использую inline style для этого.

Я хотел бы знать, есть ли способ сделать это без использования этого встроенного стиля?

Вот пример моего кода:

 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);
}
 

Как видно, каждые пять секунд изменяется индекс minorSlides изменений, следовательно, меняется и показываемый слайд. Этот индекс используется для ссылки на каждый элемент текущего слайда.

Итак, есть ли способ удалить этот встроенный стиль и сделать мой JSX более чистым?

Если бы я использовал HTML, CSS и JS, я мог бы сделать это с помощью jQuery или даже простого JS, но я не знаю, как это сделать здесь. Я знаю, что мог бы создать элемент с помощью цикла, но я бы хотел продолжать изменять только индекс, а не весь элемент.

Вот sildeshow:

введите описание изображения здесь

Комментарии:

1. Не могли бы вы поделиться картинкой или коротким видео вашего текущего вывода?

2. @Rojo Я вставил GIF. Я изменил интервал на 1500, чтобы сделать GIF короче.

3. Итак, в чем проблема с использованием inline ?

4. Нет проблем. Я просто хотел бы сделать JSX более чистым.

5. Если вы хотите удалить встроенный стиль, вы можете создать класс css для каждого цвета, и вместо установки стиля вы можете установить значение className, или вы получаете эти данные динамически?

Ответ №1:

Если вы не можете создать класс css для каждого цвета, другой вариант — добавить style тег и переопределить background-color свойство:

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

Редактировать

Также вы можете добавить тег стиля с помощью 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]);
 

Ответ №2:

Ну, в этом случае должно быть хорошо использовать встроенный стиль.

Кроме того, вы можете сделать что-то вроде:

 {
  ...
  bgClass: 'red'
}
 

добавьте этот класс в элемент div:

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

и оформите его в конце:

 .red {
  background: 'red';
}
 

Или вы можете попробовать использовать ссылку

 const ref = useRef()

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

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

<div ref={ref} />
 

Ответ №3:

Вот мои решения для того же. Кроме того, я добавляю цвета в список и использую функцию rand .

Вот список цветов

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

Я создаю переменную и добавляю к ней случайную функцию, чтобы выбрать набор цветов.

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

Просто передайте переменную в опции style в теге html div, чтобы динамически назначать цвет фона

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

Чтобы упростить задачу, просто добавьте переменную непосредственно в тег без каких-либо фигурных скобок. Также вы можете попробовать использовать эту переменную в состоянии react для лучшей загрузки. Добавьте также реквизит по умолчанию.