Изменение стиля всех элементов, кроме наведенного React

Я хочу изменить стиль всех элементов (opacity), кроме наведенного, использовал onMouseEnter и onMouseLeave, но тогда всегда стоит определенный стиль

Для примера:

function ItemList({ title, text, img, alt, id }) {
  const [useEffect, setUseEffect] = React.useState(false);

  return (
    <div
      className="item"
      id={id}
      onMouseEnter={() => setUseEffect(true)}
      onMouseLeave={() => setUseEffect(false)}
      style={useEffect ? { opacity: 1 } : { opacity: 0.4 }}
    >
      <img src={img} alt={alt} />
      <div className="tittle">
        <p>{title}</p>
        <span>{text}</span>
      </div>
    </div>
  );
}


Ответы (3 шт):

Автор решения: xydope

См. по комментариям в коде ниже

codesandbox

import { useState } from "react";
import cn from "classnames"; //https://www.npmjs.com/package/classnames

//данные 
const data = [
  {
    id: 1,
    value: "elem 1"
  },
  {
    id: 2,
    value: "elem 2"
  },
  {
    id: 3,
    value: "elem 3"
  }
];

export default function App() {
  //состояние в котором значение undefined, если нет активного, значение ID активного, если мышка наведена.
  const [active, setActive] = useState(undefined);
  const toggleActive = (id) => {
    //передаем ID, если мышка зашла на элемента
    //не передаем ID, если мышка вышла с элемента (получаем undefined)
    setActive(id);
  };
  
  return (
    <div className="App">
      {data.map(({ id, value }) => {
        const isActive = active !== id && active; //проверяем есть-ли активный и не равен ли он выбранному

        return (
          <div
            className={cn("item", { "item-opacity": isActive })}
            onMouseEnter={() => toggleActive(id)}
            onMouseLeave={() => toggleActive()}
          >
            {value}
          </div>
        );
      })}
    </div>
  );
}
.App {
  display: flex;
  gap: 1rem;
}

.item {
  flex: 0 0 100px;
  background: green;
  height: 2rem;
  transition: 0.3s opacity linear;
}

.item-opacity {
  opacity: 0.5;
}

→ Ссылка
Автор решения: Raspberry59

Можно обойтись только css. Но этот сработает только если допустимо что все элементы могут быть прозрачными, когда курсор над общей оберткой.

Допустим что у вас есть общая обертка всех элементов - .wrap При наведении на общую обертку все элементы становятся прозрачными. При наведении на элемент, он становится непрозрачным.

// стили для элементов по умолчанию
.item {}

// стили для элемента при наведении
.wrap:hover .item:hover {
  opacity: 1;
}

// стили для остальных элементов
.wrap:hover .item {
    opacity: .5;
}
→ Ссылка
Автор решения: Qwertiy

Это делается с помощью css:

main {
  display: grid;
  grid-template: "a b b" "a c d";
  grid-gap: 1em;
}

section {
  border: 1px solid;
  padding: 1em;
  text-align: center;
  background: silver;
  transition: opacity .3s linear;
}

.skip {
  display: contents;
}

.skip:hover > * {
  opacity: .25;
}

.skip:hover > :hover {
  opacity: 1;
}
<main>
  <div class="skip">
    <section style="grid-area:a">Акции</section>
    <section style="grid-area:b">Облигации</section>
    <section style="grid-area:c">ETF</section>
    <section style="grid-area:d">ИИС</section>
  </div>
</main>

Если подсветка всех при наведении на отступ между элементами не нужна, то ещё проще:

main {
  display: grid;
  grid-template: "a b b" "a c d";
  grid-gap: 1em;
}

section {
  border: 1px solid;
  padding: 1em;
  text-align: center;
  background: silver;
  transition: opacity .3s linear;
}

main:hover > * {
  opacity: .25;
}

section:hover {
  opacity: 1;
}
<main>
  <section style="grid-area:a">Акции</section>
  <section style="grid-area:b">Облигации</section>
  <section style="grid-area:c">ETF</section>
  <section style="grid-area:d">ИИС</section>
</main>

→ Ссылка