#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-анимации для достижения следующих целей —
- Создайте CSS-анимацию с использованием ключевых кадров
- Создайте состояние, чтобы вызвать анимацию, и измените состояние при печати. И это все.
Проверьте код здесь, для ссылки — 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 для добавления/удаления элемента. По общему признанию, немного многовато для этого примера, но в целом это лучший и более чистый путь.