React hooks-setInterval:导致渲染在状态更新之前开始

时间:2020-08-30 14:30:01

标签: reactjs react-hooks setinterval

我在使用React Hooks时遇到问题,特别是当我尝试运行“ setInterval”时。目前,我的应用程序有2个按钮,“下一步”和“播放”。

单击“下一步”时:运行“ onNext”功能,并呈现应用程序。

当我单击“播放”时:运行了“ onPlay”功能,但是组件在状态更新之前呈现。我相信“ setInterval”会弄乱时间,但是我不确定如何修复它或导致组件等待渲染直到状态更新。

我最初的想法是使用“ useEffect”,但是我不知道如何将其绑定到“播放”按钮中(因为您无法放置“ useEffect”或函数中的任何挂钩)。我确实尝试过:

useEffect(() => {setInterval(() => {onNext();}, 500)}), [state3D]}

但是这导致它在应用打开时开始运行。关于如何更好地进行设置的任何想法?

import React, { useState, useRef, useEffect } from "react";
import ThreePointVis from "./ThreePointVis.jsx";
// import ThreePointVis_Tut from "./ThreePointVis_Tut.jsx";
import Controls3D from "./Controls3D.jsx";
import Settings3D from "./Settings3D.jsx";

import {
  createWorld,
  create3DWorld,
  nextGen,
  randomFill,
} from "../files/game3D.jsx";
import { loadPreset } from "../files/presets3D.jsx";

import "./styles3D.css";

import React, { useState, useRef, useEffect } from "react";
import ThreePointVis from "./ThreePointVis.jsx";
// import ThreePointVis_Tut from "./ThreePointVis_Tut.jsx";
import Controls3D from "./Controls3D.jsx";
import Settings3D from "./Settings3D.jsx";

import {
  createWorld,
  create3DWorld,
  nextGen,
  randomFill,
} from "../files/game3D.jsx";
import { loadPreset } from "../files/presets3D.jsx";

import "./styles3D.css";

export const Game3D = (props) => {
  const [state3D, setState3D] = useState({
    // world3D: loadPreset("line"),
    world3D: loadPreset("plane"),
    generation: 0,
    isPlaying: false,
    colorStyle: "default",
  });

  const changeState = (props) => {
    // console.log("3d changestate: ", props);
    const { world3D, generation } = props;
    setState3D({ ...state3D, world3D: world3D, generation: generation });
  };

  const onChange = (world) => {
    // console.log("onChange: ", world);
    changeState({ world3D: world, generation: state3D.generation + 1 });
  };

  const onPlay = () => {
    console.log("3D onPlay: ", state3D.world3D);
    setState3D({ ...state3D, isPlaying: true });
    setInterval(() => {
      onNext();
    }, 500);
  };

  const onNext = () => {
    // console.log("onNext: ", state3D.world3D);
    onChange(nextGen(state3D.world3D));
  };

  const onStop = () => {
    console.log("onStop...");
    setState3D({ ...state3D, isPlaying: false });
    clearInterval();
  };

  const onSettingStyle = (settings, rules) => {
    // console.log("onsettings: ", settings, rules);
    const { colorStyle, gridSize, preset, generationSpeed } = settings;
    setState3D({
      ...state3D,
      world3D: loadPreset(`${preset}`),
      generation: generationSpeed,
      colorStyle: `${colorStyle}`,
    });
  };

  const onShuffle = () => {
    changeState({ world3D: randomFill(state3D.world3D), generation: 0 });
  };

  const onClear = () => {
    changeState({ world3D: createWorld(), generation: 0 });
  };

  // console.log("state3D:", state3D);
  return (
    <div className="container-3D">
      <Settings3D isPlaying={state3D.isPlaying} load={onSettingStyle} />
      <div className="vis-container">
        <ThreePointVis world={state3D.world3D} />
      </div>
      <Controls3D
        isPlaying={state3D.isPlaying}
        play={onPlay}
        next={onNext}
        stop={onStop}
        shuffle={onShuffle}
        clear={onClear}
      />
    </div>
  );
};

1 个答案:

答案 0 :(得分:0)

使用react生命周期方法来同步视图,而不是使用设置间隔。您可以使用componentDidMount()来设置状态。我建议阅读此https://reactjs.org/docs/state-and-lifecycle.html