Как стилизовать индивидуума <li>в отличие от всех <li>в React? - PullRequest
2 голосов
/ 10 января 2020

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

Компонент 'Service'

const Service = (props) => {

    const context = useContext(ThemeContext)

    return (
        <>
            <li className={context.cartItems.some(item => item.type === "service") ? "inCart" : ""}
                onClick={() => { context.cartItems.some(item => item) ?
                    context.removeFromCart(props) : context.addToCart(props)}} >
                {props.name}
            </li>
        </>
    )
}

Компонент 'Options', который визуализирует вышеуказанный компонент

const Options = () => {

    const context = useContext(ThemeContext)

    const serviceElements = servicesList.map(service => 
        <Service key={service.id} id={service.id} name={service.name} type={service.type} /> )

    return (
        <div className={`Options-${context.theme}`}>
            <ul>
                {serviceElements}
            </ul>
        </div>
    )
}

Методы добавления и удаления из корзины

function addToCart(newItem) { 
        cartItems.map(item => newItem.type === item.type && removeFromCart(item)) 
        setCartItems(prevItems => [...prevItems, newItem])
    }

    function removeFromCart(itemToRemove) { 
        setCartItems(prevItems => prevItems.filter(item => 
            `${item.id}-${item.type}` !== `${itemToRemove.id}-${itemToRemove.type}`)) 

    }

S css

.Options-light {
  .inCart {
    background-color: blue;
}

Ответы [ 3 ]

3 голосов
/ 12 января 2020

Похоже, пара вещей может измениться. Прежде всего, ваша className logi c в Service добавит inCart ко всем вашим li, потому что она проверяет весь массив контекста независимо от текущего реквизита. Поэтому попробуйте:

context.cartItems.find(item => item.id === props.id) ? "inCart" : ""

Также можете очистить ваши функции контента:

function addToCart(newItem) {
  // Looks like you were trying to do a check to make sure that the item isn't
  // already in the cart
  const alreadyInCart = cartItems.some(item => item.id === newItem.id);
  if (!alreadyInCart) {
    setCartItems(prevItems => [...prevItems, newItem]);
  }
}

function removeFromCart(itemToRemove) {
  // I assume id is unique because you use it as a key for the Service component
  setCartItems(prevItems => prevItems.filter(item => item.id !== itemToRemove.id));

}

Я думаю, вам, вероятно, будет лучше с toggleCartItem чтобы сделать вещи чище, и если вашей более поздней услуге «Корзина» нужен только идентификатор, то вы можете очистить дальше. Дайте мне знать, если это работает немного лучше:

const Options = () => {

  const context = useContext(ThemeContext);

  const serviceElements = servicesList.map(service => 
    <Service
      key={service.id}
      id={service.id}
      inCart={context.cartItems.some(id => service.id === id)}
    />
  );

  return (
    <div className={`Options-${context.theme}`}>
      <ul>
        {serviceElements}
      </ul>
    </div>
  )
}

const Service = (props) => {

  const context = useContext(ThemeContext);

  return (
    <li
      className={props.inCart ? "inCart" : ""}
      onClick={() => toggleCartItem(props.id)}
    >
      {props.name}
    </li>
  )
}

function toggleCartItem(newItemId) {
  const alreadyInCart = cartItems.some(id => id === newItemId);
  if (alreadyInCart) {
    setCartItems(prevIds => prevId.filter(id => id !== newItemId));
  } else {
    setCartItems(prevIds => [...prevIds, newItemId]);
  }
}
2 голосов
/ 18 января 2020

В вашем Service компоненте вы используете context.cartItems.some, чтобы определить, следует ли использовать "inCart" в качестве className. Это проблема , потому что some() будет true, если любой товаров в корзине. Это означает, что каждый <li> не будет иметь className или все с использованием «inCart».

Что вам действительно нужно, так это то, находится ли текущий товар в корзине, поэтому я рекомендую следующие изменения:

const Service = (props) => {
  const context = useContext(ThemeContext);
  const inCart = context.cartItems.find(item => item.id === props.id);
  return (
    <>
      <li className={inCart ? "inCart" : ""} 
        onClick={() => { 
          inCart ? 
            context.removeFromCart(props) : 
            context.addToCart(props)
         }} > {props.name}
      </li>
    </>
  )
}

Это установит <li className="inCart" только для элементов списка, которые находятся в корзине.

Ваш onClick также неправильно использует some(). То, как это написано, всегда будет true и всегда будет вызывать removeFromCart(props). Я изменил его, чтобы он действовал так, как я ожидал, а именно: добавьте его, если элемент отсутствует, и удалите, если он есть.

0 голосов
/ 10 января 2020

Ваш S CSS не имеет закрывающей скобки? должно быть:

.Options-light {
  .inCart {
    background-color: blue;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...