Как изменить непрозрачность с помощью ClickEvent в React?

#reactjs #settimeout

Вопрос:

Я пытаюсь изменить непрозрачность области ниже, чтобы показать пользователю, что текст скопирован.

до нажатия кнопки copyToClipboard => непрозрачность: 0 после нажатия =>> непрозрачность: 1 около 1 секунды и снова до непрозрачности:0

Я знаю, что onCopy={таймер} не сработает, но я действительно не могу понять, как подойти.

 import React, { useState, useEffect } from "react"
import { CopyToClipboard } from "react-copy-to-clipboard"

const Contact = () => {
  const [style, setStyle] = useState({ opacity: 0 })

  useEffect(() => {
    const timer = setTimeout(function () {
      setStyle({ opacity: 1 })
    }, 1000)
  }, [])

  return (
        <div>
          <CopyToClipboard text='something' onCopy={timer}>
            <LogoImage />
          </CopyToClipboard>
          <span style={style}>
            copied!
          </span>
        </div>
 

Ответ №1:

Я думаю, что вам не нужен эффект использования в этом случае. Просто создайте timer функцию вне эффекта использования, как показано ниже:-

 import React, { useState, useEffect } from "react"
import { CopyToClipboard } from "react-copy-to-clipboard"

const Contact = () => {
  const [style, setStyle] = useState({ opacity: 0 })

 const timer = () => {
    setStyle({ opacity: 1 });
    setTimeout(() => {
      setStyle({ opacity: 0 });
    }, 1000);
  };

  return (
        <div>
          <CopyToClipboard text='something' onCopy={() => timer()}>
            <LogoImage />
          </CopyToClipboard>
          <span style={style}>
            copied!
          </span>
        </div>
       )
 

Ответ №2:

Вместо использования setTimeout вы можете использовать простые CSS-анимации для достижения следующих целей —

  1. Создайте CSS-анимацию с использованием ключевых кадров
  2. Создайте состояние, чтобы вызвать анимацию, и измените состояние при печати. И это все.

Проверьте код здесь, для ссылки — https://codesandbox.io/s/festive-northcutt-kb32u?file=/src/App.js

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

1. Будет ли это работать, если пользователь нажмет второй раз?

2. Что ж, ты прав. Это сработает только один раз. Единственное, что можно сделать, — это удалить класс по завершении анимации. И ответ @OGordo служит этой цели.

Ответ №3:

Лично я бы никогда не использовал таймеры для обновлений пользовательского интерфейса. Он действительно работает (в данном случае), но он не чистый. Я бы предложил использовать CSS и переход или анимацию. Удаление/очистка имени класса в onAnimationEnd гарантирует, что анимация будет запускаться при каждом нажатии на нее. Продолжительность анимации установлена на 1,4 с, из которых (0,2/1,4) = 14,29% для затухания и 14,29% для затухания, что оставляет 1 с для отображения промежутка

CSS:

 .copied {
  opacity: 0;
  display:none;
}

.flash {
  display:inline-block;
  animation: flash 1.4s ease-in-out both;
}

@keyframes flash {
  0: {
    opacity: 0;
  }
  
  14.29% {
    opacity: 1;
  }
  
  85.71% {
    opacity: 1;
  }
  
  100% {
    opacity: 0
  }
}
 

(Упрощенный пример, чтобы удалить зависимость от буфера обмена):

 const Contact = () => {
  const [flash, setFlash] = React.useState("")

  const onClick = (event) => {
    setFlash("flash");
  }
  
  const onAnimationEnd = (event) => {
    setFlash("");
  }

  return (
        <div onClick={onClick}>
            Something
          <span className={`copied ${flash}`} onAnimationEnd={onAnimationEnd}>
            copied!
          </span>
        </div>
    )
}
 

Как и в вашем примере, у этого есть недостаток в том, что элемент должен существовать все время (хотя теперь с отображением:ни один не удален из рендеринга).

Еще лучшим подходом было бы использовать удивительную группу переходов/CSSTransition из react-transition-group для добавления/удаления элемента. По общему признанию, немного многовато для этого примера, но в целом это лучший и более чистый путь.