Skip to content Skip to sidebar Skip to footer

How To Update State After 2 Seconds?

I am trying to update my view after two seconds. But it's not calling update view, why? Here is my code https://codesandbox.io/s/practical-driscoll-5cvmm Initial view is displayed

Solution 1:

First of all, I think you should save your Graph data into your state, then in your useEffect hook, you can call setFsm to rerender your Graph.

You can also partially update your Graph data but in the following example I will just replace with your new Graph data instead.

You should also call clearTimeout in your useEffect return function to prevent memory leak in your app ( Just in case the component is unmounted before setFsm is called )

One thing I've realized on the previous answer is that, everytime fsm is updated, it will call setTimeout again, which result in fsm to update, which result in another setTimeout, essentially its like an endless loop. I've updated my answer so that the setTimeout is only called onMount, and another useEffect is just for rendering / updating the Graph. I think codes like this makes more sense.

You can use this code as your reference.

function App() {
  const [fsm, setFsm] = useState({
    init: "open",
    transitions: [
      { name: "clodsdse", from: "open", to: "closed" },
      { name: "open", from: "closed", to: "open" },
      { name: "openss", from: "closed", to: "open" },
      { name: "ss", from: "a", to: "b" }
    ]
  });

  const renderGraph = () => {
    d3.select("#graph").graphviz().renderDot(visualize(new StateMachine(fsm)));
  };

  // for graph rendering after each update
  useEffect(renderGraph, [fsm]);

  // only setTimeout onMount and clearTimeout willUnmount
  useEffect(() => {
    const timer = setTimeout(() => {
      setFsm({
        init: "open",
        transitions: [
          { name: "clodsdse", from: "open", to: "closed" },
          { name: "open", from: "closed", to: "open" },
          { name: "openss", from: "closed", to: "open" },
          { name: "ss", from: "a", to: "b" },
          { name: "sasdss", from: "a", to: "bb" }
        ]
      });
    }, 2000);
    return () => {
      clearTimeout(timer);
    };
  }, []);

  return (
    <div className="App">
      <div id="graph" />
    </div>
  );
}

Solution 2:

Don't use window.d3, use d3:

 const update = () => {
    var fsm = new StateMachine({
      init: "open",
      transitions: [
        { name: "clodsdse", from: "open", to: "closed" },
        { name: "open", from: "closed", to: "open" },
        { name: "openss", from: "closed", to: "open" },
        { name: "ss", from: "a", to: "b" },
        { name: "sasdss", from: "a", to: "bb" }
      ]
    });
    d3 // <-- not window.d3
      .select("#graph")
      .graphviz()
      .renderDot(visualize(fsm));
  };

SandBox


Solution 3:

I replace window.d3 by only d3 and it works.

const update = i => {
    var fsm = new StateMachine({
      init: "open",
      transitions: [
        { name: "clodsde" + i, from: "open", to: "closed" },
        { name: "open", from: "closed", to: "open" },
        { name: "openss", from: "closed", to: "open" },
        { name: "ss", from: "a", to: "b" },
        { name: "sasdss", from: "a", to: "bb" }
      ]
    });
    d3.select("#graph")
      .graphviz()
      .renderDot(visualize(fsm));
  };
  useEffect(() => {
    d3.select("#graph")
      .graphviz()
      .renderDot(visualize(fsm));
    var i = 0;
    setInterval(() => {
      console.log("---");
      update(i);
      i++;
    }, 2000);

Also I replace setTimeout by setInterval to update it every 2 sec.


Post a Comment for "How To Update State After 2 Seconds?"