首页 > 解决方案 > 如何在 2 秒后更新状态?

问题描述

我试图在两秒钟后更新我的视图。但它没有调用更新视图,为什么?

这是我的代码 https://codesandbox.io/s/practical-driscoll-5cvmm

显示初始视图,但两秒钟后它没有更新 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);
  }, []);

标签: javascriptreactjs

解决方案


首先,我认为您应该将 Graph 数据保存到您的状态中,然后在您的useEffect钩子中,您可以调用setFsm以重新渲染您的 Graph。

您也可以部分更新您的图表数据,但在下面的示例中,我将只替换您的新图表数据。

您还应该调用return 函数以防止应用程序clearTimeoutuseEffect的内存泄漏(以防在setFsm调用之前卸载组件)

我在上一个答案中意识到的一件事是,每次fsm更新时,它都会setTimeout再次调用,从而导致fsm更新,从而导致另一个setTimeout,本质上就像一个无限循环。我已经更新了我的答案,以便setTimeout仅调用onMount,而另一个useEffect仅用于渲染/更新图表。我认为这样的代码更有意义。

您可以使用此代码作为参考。

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

推荐阅读