Home > Net >  How can I add a class to an div after a delay based on a state change?
How can I add a class to an div after a delay based on a state change?

Time:03-14

I am looking for something like this

<div className={`${next? setTimeout(() => 'shorten', 500)  : ''}`}></div>

when next becomes true, add the 'shorten' class after 500ms

CodePudding user response:

You can use like this.

Add a state like this

const [myclass, setMyclass] = useState('');

//then define a function

function myFunction() {
setTimeout(()=> setMyclass('shorten') , 500)
}

In return stmt

{ if(next) myFunction;}

<div className={myClass}></div>

CodePudding user response:

This may be one possible solution to achieve the desired objective:

Code Snippet

const {useState} = React;

const SomeComp = () => {
  const [next, setNext] = useState(false);
  const [delayedFlag, setDelayedFlag] = useState(false);
  return (
    <div>
      <div class={next ? 'redBg' : 'cyanBg'}>
        Some Text
      </div>
      <div class={delayedFlag ? 'redBg' : 'cyanBg'}>
        Some Text with delayed update
      </div>
      <button
        onClick={() => setNext(prev => (!prev))}
      >
        Flip Color
      </button>
      <button onClick={
        () => setTimeout(() => setDelayedFlag(prev => (!prev)), 500)
       }>
        Delayed Flip
      </button>
      <button
        onClick={() => {
          setNext(prev => (!prev));
          setTimeout(
            () => setDelayedFlag(prev => (!prev)),
            750
          );
        }}
      >
        Flip Both Texts
      </button>
    </div>
  );
};

ReactDOM.render(
  <div>
    DEMO
    <SomeComp />
  </div>,
  document.getElementById('reactdiv')
);
.redBg { background-color: red; }
.cyanBg { background-color: cyan; }
<div id='reactdiv' />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>

Explanation

  • Two flags namely next and delayedFlag are declared with useState
  • Two buttons flip these flags.
  • On the delayedFlag the button onClick delays the setting by 500ms
  • Thus, the two text blocks change styles differently. There is an observable delay in the style-change for the delayedFlag controlled text

EDIT

Added a third button to flip both texts, but one is immediate and the other is with a 750ms delay.

CodePudding user response:

I think useEffect will be the correct way to do...

export default function App() {
  const [cls, setCls] = useState("");

  useEffect(() => {
    if(!next) return;
    let timeout = setTimeout(() => setCls("shorten"), 500);
    return () => clearTimeout(timeout);
  }, [next]);

  return (
    <div className={cls}>

    </div>
  );
}

Here is working snippet:

const {useEffect, useState} = React;

const App = () => {
  const [cls, setCls] = useState("");
  const [next, setNext] = useState(false);
  
  useEffect(() => {
    if (!next) return;
    let timeout = setTimeout(() => setCls("shorten"), 500);
    return () => clearTimeout(timeout);
  }, [next]);

  const resetClass = () => {
    setCls("");
    setNext(false);
  };

  return (
    <div className="main">
    <h3>Add class with delay</h3>
      <div className={cls}>THIS DIV CHANGES CLASS</div>
      <hr />
      <button onClick={() => setNext(true)}>
        Click to change "next" variable
      </button>
      <button onClick={() => resetClass()}>Clear Class</button>
    </div>
  );
}
ReactDOM.render(
  <App />,
  document.getElementById("root")
);
.shorten {
  background: red;
}

.main div{
  border:1px solid #cccccc;
  border-radius:3px;
  padding:15px;
  display:inline-block;
}

.main button{
  background:#eaeaea;
  border:1px solid #cccccc;
  margin-right:15px;
  padding:5px;
  border-radius:3px;
  cursor:pointer;
}

.main button:hover{
  background:#f1f1f1;
}

.main button:active{
  background:#f5f5f5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

  • Related