У обратных вызовов useEffect и onAnimationEnd разные значения - PullRequest
0 голосов
/ 17 января 2020

Вот весь код кнопки. У меня проблема с волновым эффектом. Когда пользователь нажимает кнопку, компонент создает новую сущность rippleElements для визуализации. На данный момент все хорошо. После окончания анимации вызывается onAnimationEnd. Проблема в том, что у меня нет последнего добавленного элемента в rippleElements. Почему? Элемент отрисован, анимация завершена, но состояние не обновлено? Как видите, у меня 2 console.log. Первый в useEffect и показывает правильные значения. Но второй, который находится в onAnimationEnd, имеет неправильное значение, и что console.log запускается ПОСЛЕ первого. В чем дело? :)

import { omit } from 'underscore';
import React, { FunctionComponent, ButtonHTMLAttributes, useState, useEffect } from 'react';
import uuid from 'uuid/v4';
import classnames from 'classnames';

export interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
    primary: boolean,
    ripple: boolean,
    additionalClass?: string,
}

const Button: FunctionComponent<Props> = (props) => {
    const [rippleElements, setRippleElements] = useState<JSX.Element[]>([]);
    useEffect(() => {
        // 1, actual - 1
        console.log(rippleElements, rippleElements.length)
    }, [rippleElements]);

    const {primary, ripple, additionalClass, children} = props;

    const classNames = classnames(
        'btn',
        {
            primary
        },
        {
            'with-ripple': ripple
        },
        additionalClass
    );

    function onAnimationEnd(key: string) {
        console.log(rippleElements.length) // 0, actual - 1
        // setRippleElements(rippleElements.filter(element => element.key !== key));
    }

    function newRippleElement(d: number, left: string, top: string) {
        const key = uuid();

        return (
            <div
                key={key}
                className="ripple"
                style={{width: d, height: d, left, top}}
                onAnimationEnd={() => onAnimationEnd(key)}
            >
            </div>
        );
    }

    function renderRippleElements() {
        return rippleElements;
    }

    return (
        <button
            className={classNames}
            {...omit(props, ['additionalClass', 'primary'])}
            onClick={(event) => {
                if (props.onClick) {
                    props.onClick(event);
                }

                if (ripple) {
                    var rect = event.currentTarget.getBoundingClientRect();

                    const d = Math.max(event.currentTarget.clientWidth, event.currentTarget.clientHeight);
                    const left = event.clientX - rect.left -d/2 + 'px';
                    const top = event.clientY - rect.top - d/2 + 'px';
                    const rippleElement = newRippleElement(d, left, top);

                    setRippleElements([...rippleElements, rippleElement]);
                }
            }}
        >
            {children}
            {renderRippleElements()}
        </button>
    );
}

export default Button;

1 Ответ

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

Исправлено с

setRippleElements(rippleElements => rippleElements.filter(element => element.key !== key));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...