Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reset React hook state with setTimeout in useEffect

I have a simple component that copies a link to the clipboard, and would like to swap the link icon with a checkmark. I have the logic setup to do so, but having an issue getting the state reset after 3 seconds to reset the button back to the link icon. How can I properly setup my useEffect and state hook to set and then reset the state for showing/hiding the link to checkmark and back again?

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>

I was trying a useEffect like so:

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

but not sure how to use the setVisible state and timeout, to swap the icon back to the link to let users know they can copy it again.

like image 381
Matt Avatar asked Nov 16 '22 01:11

Matt


1 Answers

You can derive the visible state from copySuccess state, try adding it to useEffect dep array:

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>;

See similar logic in codesandbox example:

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

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

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

Edit Q-65373145-setTimeout

like image 168
Dennis Vash Avatar answered Dec 06 '22 13:12

Dennis Vash