Как динамически изменить имя класса CSS в React

Я новичок в React и Tailwindcss, и я не могу найти решение своей проблемы. Мне нужно динамически изменить цвет фона моего компонента, но я не могу.

Я пробовал почти все, но ничего не получалось. Мне нужно сопоставить файл category.json для свойства фона. Я уже настраиваю цвета в tailwind.config.cjs.

WeeklyCard.jsx

import ellipsis from '../assets/images/icon-ellipsis.svg';

export default function WeeklyCard({
  title,
  titleBackground,
  titleImage,
  previousTime,
  currentTime,
}) {
  return (
    <div
      className = {`relative overflow-hidden flex justify-end ${titleBackground} mb-5 h-[150px] w-[290px]   rounded-[10px]`}
    >
      <img
        className='w-[65px] h-[65px] absolute -top-2 right-3 '
        src = {titleImage}
      />

      <div className='relative top-8  flex flex-col items-center justify-center h-[120px] w-[290px] rounded-[10px] p-6 bg-dark-blue  '>
        <div className='flex items-center justify-between w-full text-pale-blue'>
          <div className='text-lg'>{title}</div>
          <img className='w-[20px] h-[5px] cursor-pointer' src = {ellipsis} />
        </div>
        <div className='flex items-center justify-between w-full text-pale-blue'>
          <div className='text-[28px] font-[300]'>{currentTime}hrs</div>
          <div className='text-[14px] text-desaturated-blue'>
            Last week - {previousTime}hrs
          </div>
        </div>
      </div>
    </div>
  );
}
App.jsx

import ProfileCard from './components/ProfileCard';
import WeeklyCard from './components/WeeklyCard';
import categories from './categories.json';

export default function App() {
  const weeklyCards = categories.map((categories) => (
    <WeeklyCard
      key = {categories.title}
      title = {categories.title}
      titleBackground = {categories.titleBackground}
      titleImage = {categories.titleImage}
      previousTime = {categories.timeframes.weekly.previous}
      currentTime = {categories.timeframes.weekly.current}
    />
  ));


  return (
    <div className = {`h-min w-screen flex flex-col items-center justify-center bg-very-dark-blue`}>
      <ProfileCard
        profilePicture = {'./src/assets/images/image-jeremy.png'}
        name='Jeremy Robson'
      />
      {weeklyCards}
    </div>
  );
}


categories.json

[
  {
    "title": "Work",
    "titleImage": "../src/assets/images/icon-work.svg",
    "titleBackground": "bg-Work",
    "timeframes": {
      "daily": {
        "current": 5,
        "previous": 7
      },
      "weekly": {
        "current": 32,
        "previous": 36
      },
      "monthly": {
        "current": 103,
        "previous": 128
      }
    }
  },
  {
    "title": "Play",
    "titleImage": "../src/assets/images/icon-play.svg",
    "titleBackground": "bg-Play",
    "timeframes": {
      "daily": {
        "current": 1,
        "previous": 2
      },
      "weekly": {
        "current": 10,
        "previous": 8
      },
      "monthly": {
        "current": 23,
        "previous": 29
      }
    }
  },
  {
    "title": "Study",
    "titleImage": "../src/assets/images/icon-study.svg",
    "titleBackground": "bg-Study",
    "timeframes": {
      "daily": {
        "current": 0,
        "previous": 1
      },
      "weekly": {
        "current": 4,
        "previous": 7
      },
      "monthly": {
        "current": 13,
        "previous": 19
      }
    }
  },
  {
    "title": "Exercise",
    "titleImage": "../src/assets/images/icon-exercise.svg",
    "titleBackground": "bg-Exercise",
    "timeframes": {
      "daily": {
        "current": 1,
        "previous": 1
      },
      "weekly": {
        "current": 4,
        "previous": 5
      },
      "monthly": {
        "current": 11,
        "previous": 18
      }
    }
  },
  {
    "title": "Social",
    "titleImage": "../src/assets/images/icon-social.svg",
    "titleBackground": "bg-Social",
    "timeframes": {
      "daily": {
        "current": 1,
        "previous": 3
      },
      "weekly": {
        "current": 5,
        "previous": 10
      },
      "monthly": {
        "current": 21,
        "previous": 23
      }
    }
  },
  {
    "title": "Self Care",
    "titleImage": "../src/assets/images/icon-self-care.svg",
    "titleBackground": "bg-SelfCare",
    "timeframes": {
      "daily": {
        "current": 0,
        "previous": 1
      },
      "weekly": {
        "current": 2,
        "previous": 2
      },
      "monthly": {
        "current": 7,
        "previous": 11
      }
    }
  }
]
tailwind.config.cjs

    /** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {
      colors: {
        'blue-primary': 'hsl(246, 80%, 60%)',
        Work: 'hsl(15, 100%, 70%)',
        Play: 'hsl(195, 74%, 62%)',
        Study: 'hsl(348, 100%, 68%)',
        Exercise: 'hsl(145, 58%, 55%)',
        Social: 'hsl(264, 64%, 52%)',
        SelfCare: ' hsl(43, 84%, 65%)',
        'very-dark-blue': ' hsl(226, 43%, 10%)',
        'dark-blue': ' hsl(235, 46%, 20%)',
        'desaturated-blue': ' hsl(235, 45%, 61%)',
        'pale-blue': ' hsl(236, 100%, 87%)',
      },
    },
  },
  plugins: [],
};
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот несколько способов, которыми я это сделал.

1. Интерполяция строк

Вы можете использовать интерполяцию строк для передачи выражения непосредственно в className следующим образом:

<div className = {`${someBoolean ? "class-if-true" : "class-if-false"}`} />

2. Функция полезности

а) простой пример

Я считаю удобным использовать что-то вроде этого:

export function classNames(...classes) {
  return classes.filter(Boolean).join(' ');
}

б) библиотека вроде clsx

Вы также можете использовать такую ​​библиотеку, как clsx (https://github.com/lukeed/clsx), которая предлагает аналогичную служебную функцию, но поддерживает различные типы ввода.

Пример динамического переключения фона

Ссылка на пример: https://codesandbox.io/s/toggle-class-dynamically-example-b8gx3b

App.js

import "./styles.css";
import { useState } from "react";
function classNames(...classes) {
  return classes.filter(Boolean).join(" ");
}

export default function App() {
  const [blueBg, setBlueBg] = useState(false);
  const [hasBorder, setHasBorder] = useState(false);
  return (
    <div
      className = {classNames(
        blueBg ? "blue-bg" : "red-bg",
        hasBorder && "with-border",
        "app"
      )}
    >
      Hit the Button to Toggle Background
      <button onClick = {() => setBlueBg((prev) => !prev)}>
        Toggle Background Color
      </button>
      <button onClick = {() => setHasBorder((prev) => !prev)}>
        Toggle Border
      </button>
    </div>
  );
}

стили.css

.app {
  font-family: sans-serif;
  text-align: center;
  width: 80%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  gap: 8px;
  font-size: 30px;
  color: white;
}

.with-border {
  border: black 20px solid;
}

button {
  font-size: 20px;
}

.blue-bg {
  background-color: blue;
}

.red-bg {
  background-color: red;
}

Объяснение

Эта простая служебная функция позволяет составить список классов. Вы можете передать ему строку для любых имен классов по умолчанию. Вы также можете передать ему выражения для условного включения других имен классов. Неверные значения будут отброшены. Строки будут включены.

Пример надуманный, но принцип тот же. В вашем случае вы просто будете использовать классы Tailwind, а не произвольные пользовательские классы, которые я использовал.

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

Без функции на самом деле более читабельно для всех, кроме вас.

pguardiario 11.02.2023 01:32

Другие вопросы по теме