Не срабатывает анимация модального окна в React

Сделал три модалки с похожей логикой, но не могу понять почему у двух ModalPrice и ModalProduct анимация при закрытии и открытии работает, а у ModalReview не работает. Не один день уже потратил - ChatGTP не видит видимых проблем, в консоли и терминале ошибок нет. Буду очень признателен за помощь

//ModalPrice.js:
import React, { useEffect, useCallback, useState } from 'react'; 
import icons from './icons.svg';
import './styles.css';
const ModalPrice = ({ imgSrc, isOpen, onRequestClose }) => {
    const [isClosing, setIsClosing] = useState(false);

    const closeModal = useCallback(() => {
        setIsClosing(true);
        setTimeout(() => onRequestClose(), 500);
    }, [onRequestClose]);

    useEffect(() => {
        const handleEscape = e => isOpen && e.key === 'Escape' && closeModal();

        document.body.classList.toggle('modal-open', isOpen);
        document.body.style.overflow = isOpen ? 'hidden' : 'auto';
        document.addEventListener('keydown', handleEscape);

        return () => {
            document.removeEventListener('keydown', handleEscape);
            document.body.style.overflow = 'auto';
            setIsClosing(false);
        };
    }, [isOpen, closeModal]);

    const overlayClassName = isOpen ? 'modal_overlay active' : 'modal_overlay';
    const modalClassName = isClosing
        ? 'modal_price closing'
        : isOpen
        ? 'modal_price active'
        : 'modal_price';

    return (
        <div
            className={`${overlayClassName}`}
            id="modalOverlay"
            onClick={closeModal}
        >
            <div
                className={`${modalClassName}`}
                onClick={e => e.stopPropagation()}
            >
                <button onClick={closeModal} className="close_modal">
                    <svg className="icon_modal">
                        <use xlinkHref={`${icons}#close`} />
                    </svg>
                </button>
                <div className="image_container">
                    <img
                        src={imgSrc}
                        alt="ПРАЙС - ЛИСТ"
                        className="modal_image"
                    />
                </div>
            </div>
        </div>
    );
};
export default ModalPrice;


//ModalProduct.js:

import React, { useEffect, useState, useCallback } from 'react';
import Slider from 'react-slick';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import icons from './icons.svg';
import './styles.css';

const PrevArrow = ({ onClick }) => (
    <div className="slide_arrow prev" onClick={onClick}>
        <svg className="icon_modal">
            <use xlinkHref={`${icons}#left`} />
        </svg>
    </div>
);

const NextArrow = ({ onClick }) => (
    <div className="slide_arrow next" onClick={onClick}>
        <svg className="icon_modal">
            <use xlinkHref={`${icons}#right`} />
        </svg>
    </div>
);

const ModalProduct = ({ images, closeModal }) => {
    const [modalVisible, setModalVisible] = useState(false);
    const [isClosing, setIsClosing] = useState(false);

    const closeAnimation = useCallback(() => {
        setIsClosing(true);
        setTimeout(() => {
            setModalVisible(false);
            closeModal();
        }, 500);
    }, [closeModal]);

    useEffect(() => {
        const closeOnEsc = event => {
            if (event.key === 'Escape') {
                closeAnimation();
            }
        };

        document.body.addEventListener('keydown', closeOnEsc);
        document.body.style.overflow = 'hidden';

        return () => {
            document.body.removeEventListener('keydown', closeOnEsc);
            document.body.style.overflow = 'auto';
        };
    }, [closeAnimation]);

    const settings = {
        dots: true,
        speed: 1500,
        slidesToShow: 1,
        slidesToScroll: 1,
        autoplay: true,
        autoplaySpeed: 3000,
        infinite: true,
        pauseOnHover: false,
        prevArrow: <PrevArrow />,
        nextArrow: <NextArrow />,
    };

    useEffect(() => {
        setModalVisible(true);
    }, []);

    const overlayClassName = modalVisible
        ? 'modal_overlay active'
        : 'modal_overlay';
    const modalClassName = isClosing
        ? 'modal_product closing'
        : modalVisible
        ? 'modal_product active'
        : 'modal_product';

    return (
        <div className={`${overlayClassName}`} onClick={closeAnimation}>
            <div
                className={`${modalClassName}`}
                onClick={e => e.stopPropagation()}
            >
                <button
                    type="button"
                    className="close_modal"
                    onClick={closeAnimation}
                >
                    <svg className="icon_modal">
                        <use xlinkHref={`${icons}#close`} />
                    </svg>
                </button>
                <Slider {...settings}>
                    {images.map((imageData, index) => (
                        <div key={index} className="slide">
                            <img
                                className="slide_img"
                                src={imageData.imageSrc}
                                alt={`Slide ${index + 1}`}
                            />
                            <p
                                style={{
                                    textAlign: 'center',
                                    marginTop: '10px',
                                    width: '100%',
                                }}
                            >
                                {imageData.text.includes('(') ? (
                                    <>
                                        {imageData.text.substring(
                                            0,
                                            imageData.text.indexOf('(')
                                        )}
                                        <span
                                            style={{
                                                fontWeight: 'bold',
                                                color: 'red',
                                            }}
                                        >
                                            {imageData.text.substring(
                                                imageData.text.indexOf('(')
                                            )}
                                        </span>
                                    </>
                                ) : (
                                    imageData.text
                                )}
                            </p>
                        </div>
                    ))}
                </Slider>
            </div>
        </div>
    );
};

export default ModalProduct;


//ModalReview.js:
<code>
import React, { useState, useEffect, useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { setReviews } from '../../redux/actions';
import { addReviewApi, fetchReviewsApi } from '../../api/api';
import Notiflix from 'notiflix';
import icons from './icons.svg';
import './styles.css';

const ModalReview = ({ closeModal, onSuccess }) => {
    const [newReview, setNewReview] = useState({ name: '', comment: '' });
    const [formErrors, setFormErrors] = useState({});
    const dispatch = useDispatch();
    const [isClosing, setIsClosing] = useState(false);

    useEffect(() => {
        document.body.style.overflow = isClosing ? 'auto' : 'hidden';
    }, [isClosing]);

    const closeModalWithAnimation = useCallback(() => {
        setIsClosing(true);
        setTimeout(() => {
            setIsClosing(false);
            closeModal();
        }, 500);
    }, [closeModal]);

    const handleEscape = useCallback(
        e => {
            if (e.key === 'Escape') {
                closeModalWithAnimation();
            }
        },
        [closeModalWithAnimation]
    );

    useEffect(() => {
        document.addEventListener('keydown', handleEscape);

        return () => {
            document.removeEventListener('keydown', handleEscape);
        };
    }, [handleEscape]);

    const validateForm = () => {
        const errors = {};
        if (!newReview.name.trim()) {
            errors.name = 'Не введено имя.';
        }
        if (!newReview.comment.trim()) {
            errors.comment = 'Не введен комментарий.';
        }
        return errors;
    };

    const handleInputChange = e => {
        const { name, value } = e.target;
        setNewReview({ ...newReview, [name]: value });
    };

    const handleSubmit = async e => {
        e.preventDefault();

        const errors = validateForm();
        setFormErrors(errors);
        if (Object.keys(errors).length === 0) {
            try {
                await addReviewApi(newReview);
                const reviews = await fetchReviewsApi();
                dispatch(setReviews(reviews));
                onSuccess();
                closeModalWithAnimation();
            } catch (error) {
                console.error('Ошибка при добавлении отзыва:', error);
            }
        } else {
            Notiflix.Notify.failure('Будь ласка, заповніть усі поля форми.', {
                position: 'center-center',
                timeout: 2000,
            });
        }
    };

    return (
        <div
            className={`modale_overlay ${isClosing ? 'closing' : ''} ${
                isClosing ? '' : 'active'
            }`}
            onClick={closeModalWithAnimation}
        >
            <div
                className={`modale_content ${isClosing ? 'closing' : ''} ${
                    isClosing ? '' : 'active'
                }`}
                onClick={e => e.stopPropagation()}
            >
                <button
                    className="close_modal"
                    onClick={closeModalWithAnimation}
                >
                    <svg className="icon_modal">
                        <use xlinkHref={`${icons}#close`} />
                    </svg>
                </button>
                <form className="reviews_form" onSubmit={handleSubmit}>
                    <label className="reviews_label">
                        Ім'я:
                        <input
                            className="reviews_input"
                            type="text"
                            name="name"
                            value={newReview.name}
                            autoComplete="name"
                            onChange={handleInputChange}
                        />
                        {formErrors.name && (
                            <div style={{ display: 'none' }}>
                                {formErrors.name}
                            </div>
                        )}
                    </label>
                    <br />
                    <label>
                        Коментар:
                        <textarea
                            className="reviews_textarea"
                            name="comment"
                            value={newReview.comment}
                            autoComplete="comment"
                            onChange={handleInputChange}
                        />
                        {formErrors.comment && (
                            <div style={{ display: 'none' }}>
                                {formErrors.comment}
                            </div>
                        )}
                    </label>
                    <br />
                    <button className="reviews_button modale" type="submit">
                        ВІДПРАВИТИ ВІДГУК
                    </button>
                </form>
            </div>
        </div>
    );
};

export default ModalReview;

и общий файл со стилями для этих модалок:

/* !-------------------Modal All-------------------------- */

.modal_overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: var(--color-overlay-body);
    z-index: 2000;
    opacity: 0;
    visibility: hidden;
}

.modal_overlay.active {
    opacity: 1;
    visibility: visible;
}

.image_container {
    overflow-y: auto;
    max-height: calc(100vh - 150px);
    margin-top: 10px;
}

.modal_image {
    width: 100%;
    height: auto;
    object-fit: contain;
}

.close_modal {
    position: absolute;
    top: 8px;
    right: 8px;
    display: flex;
    justify-content: center;
    align-items: center;
    text-decoration: none;
    border-radius: 50%;
    border: 1px solid var(--color-backdrop);
    width: 30px;
    height: 30px;
    cursor: pointer;
    padding: 0;
    margin: 0;
    color: var(--color-general);
    background-color: var(--background-general);
    transition: color var(--transition-timing) var(--transition-duration);
}

.close_modal:hover,
.close_modal:focus {
    color: var(--color-nav-link);
}

.icon_modal {
    width: 20px;
    height: 20px;
    fill: currentColor;
    align-items: center;
}

/* !-----------------Modal Price-------------------------- */

.modal_price {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 95%;
    height: 100%;
    max-width: 820px;
    max-height: 680px;
    background-color: var(--background-slogan);
    border-radius: 8px;
    padding: 40px;
    margin: 0;
    z-index: 3000;
    transform: translate(-50%, -50%) scale(0);
    opacity: 0;
    transition: opacity var(--transition-duration-product),
        transform var(--transition-duration-product);
}

.modal_price.active {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
}

.modal_price.closing {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0);
    transition: opacity var(--transition-duration-product),
        transform var(--transition-duration-product);
}

/* !---------------Modal Product-------------------------- */

.modal_product {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    max-width: 550px;
    max-height: 630px;
    background-color: var(--background-slogan);
    border-radius: 8px;
    padding: 40px;
    margin: 0;
    z-index: 1000;
    transform: translate(-50%, -50%) scale(0);
    opacity: 0;
    transition: transform var(--transition-timing) var(--transition-duration-product),
        opacity var(--transition-timing) var(--transition-duration-product);
}

.modal_product.active {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
}

.modal_product.closing {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0);
    transition: opacity var(--transition-duration-product),
        transform var(--transition-duration-product);
}

@media screen and (max-width: 1200px) {
    .modal_product {
        max-width: 450px;
        max-height: 580px;
    }
}

/* !---------------Slider Product-------------------------- */

.slide {
    margin-top: 20px;
}

.slide_img {
    width: 100%;
    height: 100%;
    margin: 0 auto;
    max-width: 400px;
    max-height: 500px;
    border-radius: 8px;
    object-fit: contain;
    object-position: center;
}

.slide_arrow {
    position: absolute;
    top: 260px;
    width: 40px;
    height: 40px;
    background-color: var(--background-general);
    color: var(--color-general);
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid var(--color-backdrop);
    border-radius: 50%;
    cursor: pointer;
    transition: color var(--transition-timing) var(--transition-duration);
    z-index: 1;
}

.slide_arrow.prev {
    left: 5px;
}

.slide_arrow.next {
    right: 5px;
}

.slide_arrow:hover,
.slide_arrow:focus {
    color: var(--color-nav-link);
}

/* !---------------Modal Review-------------------------- */

.modale_overlay {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: var(--color-overlay-body);
      z-index: 2000;
      opacity: 0;
      visibility: hidden;
}

.modale_overlay.active {
      opacity: 1;
      visibility: visible;
}

.modale_content {
      position: fixed;
      top: 50%;
      left: 50%;
      background-color: var(--background-slogan);
      padding: 40px;
      padding-top: 20px;
      border-radius: 8px;
      z-index: 1051;
      transform: translate(-50%, -50%) scale(0);
      opacity: 0;
      visibility: hidden;
      transition: transform 500ms, opacity 500ms;
}

.modale_content.active {
      transform: translate(-50%, -50%) scale(1);
      opacity: 1;
      visibility: visible;
      transition-delay: 0ms;
}

.modale_content.closing {
    opacity: 0;
    visibility: hidden;
    transform: translate(-50%, -50%) scale(0);
    transition: transform 500ms, opacity 500ms;
}

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