user944513
user944513

Reputation: 12729

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 but after two seconds it is not updating the DOM.

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" }
    ]
  });

  useEffect(() => {
    d3.select("#graph")
      .graphviz()
      .renderDot(visualize(fsm));
    setTimeout(() => {
      console.log("---");
      update();
    }, 2000);
  }, []);

Upvotes: 1

Views: 535

Answers (3)

junwen-k
junwen-k

Reputation: 3644

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

Upvotes: 4

Mahesh S
Mahesh S

Reputation: 395

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.

Upvotes: 2

Taki
Taki

Reputation: 17654

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

Upvotes: 2

Related Questions