Анимировать компонент, щелкнув другой компонент - PullRequest
2 голосов
/ 31 октября 2019

Я создаю интернет-магазин и хочу анимировать логотип корзины, когда кто-то нажимает на кнопку «Добавить в корзину».

Кнопка «Добавить в корзину» является частью компонента элемента коллекции, а значок корзины -другой компонент внутри заголовка. Они не связаны друг с другом.

У меня есть анимация css, но мне нужна помощь для соединения между различными компонентами.

Я добавляю фрагменты кода соответствующих компонентов:

import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";

import { toggleCartHidden } from "../../redux/cart/cart.actions";
import { selectCartItemsCount } from "../../redux/cart/cart.selectors";

import {
  CartContainer,
  ShoppingIcon,
  ItemCountContainer
} from "./cart-icon.styles";

const CartIcon = ({ toggleCartHidden, itemCount }) => (
  <div className="hvr-buzz-out">
    <CartContainer onClick={toggleCartHidden}>
      <ShoppingIcon />
      <ItemCountContainer>{itemCount}</ItemCountContainer>
    </CartContainer>
  </div>
);

const mapDispatchToProps = dispatch => ({
  toggleCartHidden: () => dispatch(toggleCartHidden())
});

const mapStateToProps = createStructuredSelector({
  itemCount: selectCartItemsCount
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(CartIcon);

import React from 'react';
import { connect } from 'react-redux';

import { addItem } from '../../redux/cart/cart.actions';

import {
  CollectionItemContainer,
  CollectionFooterContainer,
  AddButton,
  BackgroundImage,
  NameContainer,
  PriceContainer
} from './collection-item.styles';

const CollectionItem = ({ item, addItem }) => {
  const { name, price, imageUrl } = item;

  return (
    <CollectionItemContainer>
      <BackgroundImage className='image' imageUrl={imageUrl} />
      <CollectionFooterContainer>
        <NameContainer>{name}</NameContainer>
        <PriceContainer>{price}&#8362;</PriceContainer>
      </CollectionFooterContainer>
      <AddButton onClick={() => addItem(item)} inverted>
        Add to cart
      </AddButton>
    </CollectionItemContainer>
  );
};

const mapDispatchToProps = dispatch => ({
  addItem: item => dispatch(addItem(item))
});

export default connect(
  null,
  mapDispatchToProps
)(CollectionItem);

Как это можно сделать?

Кстати, контейнеры - это просто стилизованные компоненты.

Заранее спасибо.

1 Ответ

1 голос
/ 31 октября 2019

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

someOtherClass будет добавлено при изменении itemCount и удалено после завершения анимации. Если анимация по ключевым кадрам, используйте onAnimationEnd вместо onTransitionEnd

import React, { useEffect, useState, useRef } from 'react';

...

export const CartIcon = ({ toggleCartHidden , itemCount }) => {
  const [animate, setAnimate] = useState(false);
  const isMounting = useRef(true);

  useEffect(() => {
    if (isMounting.current) { //No animation on initial mount
      isMounting.current = false; 
    } else {
      setAnimate(true); // Set animate to true
    }
  }, [itemCount]); //Only run useEffect if itemCount has changed

  const className = `hvr-buzz-out${animate ? ' classForAnimate' : ''}`
  return (
    <div className={className} onTransitionEnd={() => setAnimate(false)}>
      <CartContainer onClick={toggleCartHidden} >
        <ShoppingIcon />
        <ItemCountContainer>{itemCount}</ItemCountContainer>
      </CartContainer>
    </div>
  );
}

css может быть что-то вроде

.hvr-buzz-outate {
  background-color: red;
  transition: all 1s ease-in;
}
.classForAnimate {
  background-color: blue;
}
...