on React Button onClick,启动和停止一个函数(方法)

时间:2017-11-12 21:13:22

标签: javascript reactjs

有一个唠叨的问题,并想知道是否有人可以解释一下。

我创建了一个功能,可以自动为我的反应应用程序进行路由...但我正在尝试将一个按钮附加到此功能,以确保它在按钮单击时启动和停止。但是,当我尝试下面的代码时......没有任何反应

class App extends React.Component {
  constructor (props) {
  super(props);
  this.state = { tabControl: true };
  this.handleClick = this.handleClick.bind(this);
  this.tabControl = this.tabControl.bind(this);
}

tabControl(props){
    RoutePaths(this.props);
}
handleClick() {
    this.setState(function (prevState, props){
      return { tabControl: !prevState.tabControl }
  });

}

render() {

return (
    <div className="clearfix" id="topContent">
          <Sidebar />
          <div className="white-bg" id="page-wrapper">
              <Header tagline="Welcome to JuDGE" />

             <button className="AutoTab" onClick={this.handleClick}>
                Toggle
              </button>

........

但是当我尝试第二个代码时,Tab键功能会在点击按钮时启动,但当你再次点击按钮时当然不会停止。

 class App extends React.Component {

 constructor (props) {
  super(props);
  this.state = { tabControl: true };
  this.handleClick = this.handleClick.bind(this);
  this.tabControl = this.tabControl.bind(this);
}

 tabControl(props){
    RoutePaths(this.props);
 }


  handleClick() {
    this.setState(function (prevState, props){
      return { tabControl: !prevState.tabControl }
  });

 }

 render() {

 return (
    <div className="clearfix" id="topContent">
          <Sidebar />
          <div className="white-bg" id="page-wrapper">
              <Header tagline="Welcome to JuDGE" />

             <button className="AutoTab" onClick={this.tabControl}>
                Toggle
              </button>

3 个答案:

答案 0 :(得分:1)

尝试使用当前状态而不是setState中的可选回调:

handleClick() {
  this.setState({ tabControl: !this.state.tabControl });
}

答案 1 :(得分:1)

我不确定我是否完全得到你想要做的事情,但在我看来你忘记了一个条件。
你说如果你调用这个方法:

tabControl(props){
    RoutePaths(this.props);
 }

它有效,但不会停止。

嗯,你没有条件地运行它。
在这种方法中:

handleClick() {
    this.setState(function (prevState, props){
      return { tabControl: !prevState.tabControl }
  });

}

您正在设置tabControl状态。我想你在运行tabControl()之前忘了检查它。

tabControl(props){
    const {tabControl} = this.state;
    tabControl && RoutePaths(this.props); // invoke of tabControl is true
 }

修改

在您发表评论后看到RoutePaths的代码:

function RoutePaths(props) {
    let pathUrls = ['/deploymentqueue', '/deploydb', '/currentstatus'];
    let paths = pathUrls.length;
    let index = 0;
    let interval = 3000;
    setInterval(() => {
        props.history.push(pathUrls[index]);
        index = (index + 1) % paths;
    }, interval);
} 

在我看来,你会遇到另一个问题。您需要从setInterval返回的间隔的ID才能停止它,但您没有将其存储在任何地方。
引自docs

  

...它返回一个唯一标识间隔的间隔ID,   所以你可以稍后通过调用clearInterval()...

删除它

因此,您需要将其存储在某处并使用clearInterval致电ID

this.intervalId = setInterval(() => {...});

你班上的其他地方:

clearInterval(this.interval);

编辑#2

作为评论的后续内容,以下是使用react的简单用法:

&#13;
&#13;
class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      ticks: 0
    };
  }

  onStart = () => {
    this.intervalId = setInterval(() => {
      this.setState({ ticks: this.state.ticks + 1 })
    }, 500);
  }

  onStop = () => {
    clearInterval(this.intervalId)
  }

  render() {
    const { ticks } = this.state;
    return (
      <div>
        <button onClick={this.onStart}>Start</button>
        <button onClick={this.onStop}>Stop</button>
        <div>{ticks}</div>
      </div>
    );
  }
}

ReactDOM.render(<Timer />, document.getElementById("root"));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
&#13;
&#13;
&#13;

所以你可以尝试这种方法,
RoutePaths将返回间隔ID:

function RoutePaths(props) {
    let pathUrls = ['/deploymentqueue', '/deploydb', '/currentstatus'];
    let paths = pathUrls.length;
    let index = 0;
    let interval = 3000;
    return setInterval(() => {
        props.history.push(pathUrls[index]);
        index = (index + 1) % paths;
    }, interval);
}

tabControl将存储ID并有条件地调用或清除间隔:

tabControl() {
    const { tabControl } = this.state;
    if (tabControl && this.intervalId) { // i'm not sure this is the condition you want, but you can play with it
        clearInterval(this.intervalId);
    } else {
        this.intervalId = RoutePaths(this.props);
    }
}

我还没有对此代码进行过测试,但我认为它可以让您有一个良好的开端。

答案 2 :(得分:0)

您不需要tabControl状态来执行您要执行的操作。但是,您需要在某处调用clearInterval。更改你的句柄点击这样的东西:

&#13;
&#13;
handleClick() {
  // change RoutePath to return the id that setInterval returns.
  if (this.routePathInterval) {
    clearInterval(this.routePathInterval);
    this.routePathInterval = null;
  } else {
    this.routePathInterval = RoutePath(this.props);
  }
}
&#13;
&#13;
&#13;

此外,当您调用clearInterval然后再次启动它时,您的索引将从零开始。如果要从您所在的索引中恢复,您可能希望将当前索引保持在状态并将其传递给RoutePath。

修改

第二个想法是,您不需要将索引保持在状态,因为您不希望在递增时触发重新渲染。但是,您应该将索引设为实例变量,并使RoutePath成为App组件的实例方法。

首先,在构造函数中初始化this.index = 0;,然后:

&#13;
&#13;
routePaths() {
    let pathUrls = ['/deploymentqueue', '/deploydb', '/currentstatus'];
    let paths = pathUrls.length;
    let interval = 3000;
    return setInterval(() => {
        this.props.history.push(pathUrls[index]);
        this.index = (this.index + 1) % paths;
    }, interval);
}
&#13;
&#13;
&#13;