#javascript #css #reactjs #timeout #settimeout
#javascript #css #reactjs #тайм-аут #settimeout
Вопрос:
Возможно, я думаю об этом неправильно. Поэтому любые рекомендации были бы очень полезны.
У меня есть элемент, затем при нажатии открывается несколько переключателей. Нажатие одной из переключателей запускает setTimeout
2300ms
это, добавит класс Frequency--closing
к элементу Frequency
, который запускает анимацию в css, по истечении времени ожидания этот компонент удаляется из DOM.
Я использую тайм-аут как средство разрешения анимации до того, как она будет удалена из DOM.
То, к чему я стремлюсь, — это когда я нажимаю переключатель, а затем нажимаю другой переключатель, прежде чем компонент будет удален из DOM, который сбрасывает таймер, поэтому при 2-м щелчке он ожидает другого 2300ms
, прежде чем он будет удален из DOM.
Ниже приведен компонент, который использует состояние, чтобы определять, будет ли элемент открыт или закрыт с onToggle()
помощью функции
const SavedSearchBox = ({ modifier, search, loading }) => {
const [frequencyToggled, setFrequencyToggled] = useState(false);
const [closeFrequency, setCloseFrequency] = useState(false);
const timeoutRef = useRef(null);
const onToggle = () => {
if (frequencyToggled) {
setCloseFrequency(true);
timeoutRef.current = setTimeout(
() => setFrequencyToggled(!frequencyToggled),
2300
);
} else {
setCloseFrequency(false);
setFrequencyToggled(!frequencyToggled);
clearTimeout(timeoutRef.current);
}
};
useEffect(() => () => clearTimeout(timeoutRef.current), []);
return (
<div
className={`SavedSearchBox ${modifier ? modifier : ""} ${
loading amp;amp; loading.status ? "SavedSearchBox--loading" : ""
}`}
>
<div className="SavedSearchBox-footer">
{frequencyToggled ? (
<Frequency
closeFrequency={closeFrequency}
onChange={() => onToggle()}
/>
) : (
<div onClick={() => onToggle()}>Click Here</div>
)}
</div>
</div>
);
};
onToggle()
Функция также вызывается из дочернего компонента Frequency
. Этот компонент также включает класс Frequency--closing
для анимации закрытия.
const Frequency = props => {
const [active, setActive] = useState(0);
const inputs = [
["Instant Alerts", "Instant"],
["Twice Daily Alerts", "Twice"],
["Daily Alerts", "Daily"],
["Weekly Alerts", "Weekly"],
["No Email Alerts", "None"]
];
return (
<div
className={`Frequency ${
props.closeFrequency ? "Frequency--closing" : ""
}`}
>
<div className="Frequency-list">
{inputs.map(([text, value], i) => (
<div key={i} className="Frequency-listItem">
<label className="Frequency-listLabel">
{text}
<input
type="radio"
checked={value === inputs[active][1]}
onChange={() => {
props.onChange();
setActive(i);
}}
value={value}
/>
<span className="Frequency-listRadio" />
</label>
</div>
))}
</div>
</div>
);
};
Вот анимации в случае, если это, возможно, вызывает эту проблему
.Frequency-listItem {
animation: enter $Frequency-duration $Frequency-easing backwards;
transform: translateY(0%);
transition: transform $Frequency-duration ease;
display: flex;
justify-content: left;
align-items: center;
@for $i from 1 through 6 {
amp;:nth-of-type(#{$i}) {
animation-delay: calc(#{$i} * #{$Frequency-delay});
}
}
}
.Frequency--closing .Frequency-listItem {
animation: exit $Frequency-exitDuration $Frequency-easing both 1;
transform: translateY(100%);
transition: transform $Frequency-exitDuration ease;
@for $i from 6*-1 through -1 {
amp;:nth-of-type(#{abs($i)}) {
animation-delay: calc(#{abs($i)} * #{$Frequency-exitDelay} 2s);
}
}
}
@keyframes enter {
from {
opacity: 0;
padding: 0;
margin: 0;
max-height: 0;
transform: scale(.7);
}
}
@keyframes exit {
from {
opacity: 1;
max-height: 100%;
transform: scale(1);
}
to {
opacity: 0;
padding: 0;
margin: 0;
max-height: 0;
transform: scale(.7);
}
}
Вот CODESANBOX, если вы хотите его протестировать
Любая помощь будет принята с благодарностью!
Комментарии:
1. Похоже, это работает: codesandbox.io/s/1v556xj14j (В основном я изменил основной файл, но также убрал
2s
задержку из анимации закрытия.2. @Chris G Это сработало отлично, спасибо. Не думал об использовании 2 таймаутов!