Компоненты в стиле React — Как отображать стили на основе условия prop или псевдокласса?

#javascript #css #reactjs #sass #styled-components

#javascript #css #reactjs #sass #styled-components

Вопрос:

Я пытаюсь условно отобразить состояние / вид наведения в стилизованных компонентах, используя реквизиты, поступающие из react…

В настоящее время мой код выглядит примерно так:

 ${isHovered}, amp;:hover {
    background: red;
}
  

К сожалению, это не помогает иметь значение true / false, поскольку я упускаю что-то, что, как я полагаю, может выполнять либо / либо псевдо..

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

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

1. Не элегантно, но должно работать background: ${props => props.isHovered ? 'red': 'inherit'}; amp;:hover { background: red}

2. @YuryTarabanko ах, это действительно работает, но вызывает МНОГО дублирования кода.. было бы неплохо иметь что-то такое же простое, как variable, amp;:hover для того, чтобы охватить оба экземпляра: (

Ответ №1:

То, как у вас есть ваши селекторы прямо сейчас, недопустимо:

Проблема

 ${isHovered}, amp;:hover {
    background: red;
}
  

На данный момент это всегда будет переводиться в:

 undefined, amp;:hover {
    background: red;
}
  

Для простоты, чтобы правильно интерполировать, это должна быть функция, принимающая props , которая возвращает string :

 color: ${props => props.isHovered amp;amp; "pink" };
  

В связи с этим, даже если вы обернули свой стилизованный компонент в компонент более высокого порядка, где isHovered определяется как аргумент, он, к сожалению, все равно не будет работать в рабочей среде для styled-components v5 — это работало в v4, но v5.x не обрабатывает должным образом css-интерполяции в стилизованном компоненте при компиляции дляпроизводство (см. Отслеживание проблем здесь).

Решения

Лучшим и рекомендуемым подходом было бы интерполировать внутри свойства CSS:

   background: ${({ isHovered }) => isHovered amp;amp; "red"};

  :hover {
    background: red;
  }
  

В качестве альтернативы, если у вас есть несколько правил CSS, вы можете выполнять интерполяцию вне свойства CSS:

 
  ${({ isHovered }) => isHovered amp;amp; "background: red;color: white;"};

  :hover {
    background: red;
  }

  

Теперь вы просто передаете свой компонент в isHovered prop.

 <StyledComponent isHovered={isHovered} />
  

Хотя технически вы можете это сделать (обратите внимание, что значения falsey приравниваются к true, что может быть ошибкой или необработанным краевым случаем)…

 ${({ isHovered }) => !isHovered amp;amp; ".hovered"}, amp;:hover {
    background: red;
}
  

… это НЕ рекомендуется из-за того, как это интерпретируется:

 ".hovered", amp;:hover {
    background: red;
}
  

Возможно, это не то, что вы хотели бы, потому .hovered что оно вообще не используется в DOM, что может сбить с толку других разработчиков. Вместо этого он повторно использует скомпилированное имя хэшированного класса для добавления свойства CSS в другое правило (сосредоточьтесь на Styles вкладке, чтобы увидеть разницу):
скриншот

В то время как рекомендуемый подход устанавливает свойство CSS для хэшированного класса в том же блоке правил: скриншот


Рабочая демонстрация (эта демонстрация включает оба примера кода выше, где Title используется рекомендуемый подход и SubTitle нет):

Редактирование компонентов в стиле - Родительское наведение

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

1. Спасибо за исчерпывающее объяснение, ценю это!

Ответ №2:

 import styled, { css } from 'styled-components';

const getHoverStyle = (props) => {
   if(props?.isHovered) {
       return ( 
         css` 
            amp;:hover {
               background: red;
            } 
         `
       )
    }
 }
 export const SomeName = styled.div`
    ${getHoverStyle}
 `;
  

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

1. Проверка наведена в props, как props? .Завис. Спасибо

Ответ №3:

Вы можете использовать class селектор для применения стиля, а в вашем стилизованном компоненте вы можете использовать attr call для установки className атрибута на основе значения свойства, например:

 const MyComp = styled.div.attrs((props) => ({
  className: props.isHovered ? "hovered" : ""
}))`
  color: ${(props) => props.color};
  amp;.hovered,
  amp;:hover {
    color: blue;
  }
`;
  

Взгляните на эту песочницу react.

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

1. @BryceSnyder это то, что вы ищете?

Ответ №4:

Я создал интерактивную игровую площадку. Вы можете перейти по ссылке ниже. Это может вам помочь.

https://codesandbox.io/s/focused-sky-vp8d9?file=/src/App.js

Ниже приведен код.

 import React, { useState } from "react";
import "./styles.css";
import styled, { css } from "styled-components";

const HoverExample = styled.div`
  background: pink;
  width: 100%;
  min-height: 80px;

  ${(props) =>
    props.isHovered amp;amp;
    css`
      amp;:hover {
        background: green;
      }
    `}
`;

export default function App() {
  const [isHovered, setisHovered] = useState(false);
  return (
    <div className="App">
      <button onClick={() => setisHovered(!isHovered)}>
        {!isHovered ? "Enable" : "disabled"} Hover
      </button>
      <p>Hover is {isHovered ? "enabled" : "disabled"}</p>
      <HoverExample isHovered={isHovered}></HoverExample>
    </div>
  );
}
  

Спасибо.