Как сбросить состояние хука React с помощью setTimeout в useEffect

У меня есть простой компонент, который копирует ссылку в буфер обмена и хотел бы поменять местами значок ссылки с галочкой. У меня есть логическая настройка для этого, но возникла проблема со сбросом состояния через 3 секунды, чтобы сбросить кнопку обратно на значок ссылки. Как я могу правильно настроить свой useEffect и хук состояния, чтобы установить, а затем сбросить состояние для отображения/скрытия ссылки на галочку и обратно?

const [copySuccess, setCopySuccess] = useState('');
const [visible, setVisible] = useState(true);
const copyToClipBoard = async copyHeader => {
try {
  await navigator.clipboard.writeText(copyHeader);
    setCopySuccess('Copied!');
  } catch (err) {
    setCopySuccess('Failed to copy!');
  }
};

<Button>
    {copySuccess ? (
       <Icon name = "success" />
    ):(
     <Icon
        name = "linked"
        onClick = {() => copyToClipBoard(url)}
     />
    )}
</Button>

Я пробовал useEffect вот так:

useEffect(() => {
    setTimeout(() => {
      setVisible(false);
    }, 3000);
 });
  

но не уверен, как использовать состояние setVisible и время ожидания, чтобы заменить значок обратно на ссылку, чтобы пользователи знали, что они могут скопировать его снова.

Попробуйте включить copySuccess в качестве зависимости в массив зависимостей useEffect.

BlackMath 19.12.2020 19:33
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
5
1
1 187
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете получить видимое состояние из состояния copySuccess, попробуйте добавить его в массив useEffect dep:

const [copySuccess, setCopySuccess] = useState("");
const copyToClipBoard = async (copyHeader) => {
  try {
    await navigator.clipboard.writeText(copyHeader);
    setCopySuccess("Copied!");
  } catch (err) {
    setCopySuccess("Failed to copy!");
  }
};

useEffect(() => {
  if (copySuccess !== "") {
    setTimeout(() => {
      setCopySuccess("");
    }, 3000);
  }
}, [copySuccess]);

<Button>
  {copySuccess ? (
    <Icon name = "success" />
  ) : (
    <Icon name = "linked" onClick = {() => copyToClipBoard(url)} />
  )}
</Button>;

См. аналогичную логику в примере codeandbox:

function Component() {
  const [copyIsAvailable, setCopyIsAvailable] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setCopyIsAvailable(true);
    }, 1000);
  }, [copyIsAvailable]);

  return (
    <button onClick = {() => setCopyIsAvailable(false)}>
      {copyIsAvailable ? "copy" : "copied"}
    </button>
  );
}

Я мог бы предложить вам изменить асинхронную функцию на обновление visible.
Затем измените тег кнопки:

<Button>
    {visible 
      ? <Icon name = "success" />
      : <Icon
         name = "linked"
         onClick = {() => copyToClipBoard(url)}
        />
    }
</Button>

Другие вопросы по теме