我不知道如何在我的第一个ReactJS应用

时间:2017-07-05 06:57:27

标签: reactjs

我已经在react中创建了一个简单的计时器应用程序,您可以输入一个数字并开始倒计时。仅仅为了#34;学习反应" - 目的我实现了一个API来存储已设置的计时器。他们在componentDidMount上阅读。您可以使用按钮逐个删除它们。问题:启动计时器是在一个不同的组件,并不知道" RecentTimers"零件。我不确定如何通过反应正确地做到这一点。

这是关心实际计时器的组件:

import React, { Component } from 'react';
import Axios from 'axios';
import ProgressBar from './ProgressBar';
import Input from './Input';
import Message from './Message';
import RecentTimers from './RecentTimers';

export default class Timer extends Component {
  constructor(props) {
    super(props);

    this.state = {
      running: false,
      secsStart: 0,
      secsRemaining: 0
    };

    this.startTimer = this.startTimer.bind(this);
    this.tick = this.tick.bind(this);
  }

  startTimer(startValue) {
    this.setState({
      running: true,
      secsStart: startValue,
      secsRemaining: startValue
    });

    this.timer = setInterval(this.tick, 1000);

    this.saveTimer(startValue);
  }

  saveTimer(startValue) {
    Axios.post('http://rest.learncode.academy/api/svartberg/timers', {
        timestamp: + new Date(),
        seconds: startValue
      })
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        UIkit.notification({
          message: 'Couldn\'t save the timer.<br />' + error,
          status: 'danger',
          pos: 'bottom-right'
        });
      });
  }

  tick() {
    if (this.state.running) {
      if (this.state.secsRemaining > 0) {
        this.setState({
          secsRemaining: this.state.secsRemaining - 1
        });
      } else {
        this.setState({
          running: false
        });
        clearInterval(this.timer);
      }
    }
  }

  renderProgress() {
    return this.state.secsRemaining <= 0
      ? <Message>Der Timer ist abgelaufen.</Message>
      : <ProgressBar
          secsRemaining={this.state.secsRemaining}
          secsStart={this.state.secsStart}
        />;
  }

  render() {
    return (
      <div className="uk-container uk-container-center uk-margin-large-top uk-margin-large-bottom">
        <h1 className="uk-text-center">Simple Timer</h1>
        <Input startFunc={this.startTimer} status={this.state.running} />
        <div className="uk-text-center uk-margin-top">
          <span className="uk-text-lead">{this.state.secsRemaining}</span>{' '}
          seconds left.
        </div>
        { this.renderProgress() }
        <RecentTimers />
      </div>
    );
  }
}

这是关注最近使用的计时器列表的组件:

import React, { Component } from 'react';
import Axios from 'axios';

import UIkit from 'uikit';
import Icons from 'uikit/dist/js/uikit-icons';

UIkit.use(Icons);

export default class RecentTimers extends Component {

  constructor() {
    super();
    this.state = {
      loading: true,
      recentTimers: []
    };
  }

  componentDidMount() {
    this.getRecentTimers();
  }

  getRecentTimers() {
    this.setState({ loading: true });

    Axios.get('http://rest.learncode.academy/api/svartberg/timers')
      .then((response) => {
        this.setState({
          loading: false,
          recentTimers: response.data.reverse()
        });
      })
      .catch(function (error) {
        UIkit.notification({
          message: 'Couldn\'t fetch recent timers.<br />' + error,
          status: 'danger',
          pos: 'bottom-right'
        });
      });
  }

  deleteRecentTimerItem(item) {
    Axios.delete('http://rest.learncode.academy/api/svartberg/timers/' + item.id)
      .then((response) => {
        this.getRecentTimers();

        UIkit.notification({
          message: 'Item deleted',
          status: 'success',
          pos: 'bottom-right'
        });
      })
      .catch(function (error) {
        UIkit.notification({
          message: 'Couldn\'t delete timer with ID ' + item.id + '.<br />' + error,
          status: 'danger',
          pos: 'bottom-right'
        });
      });
  }

  renderRecentTimerItems() {
    if (this.state.loading) {
      return <div className="uk-text-center"><span data-uk-spinner={''} /></div>;
    } else {
      return this.state.recentTimers.length > 0
        ? this.state.recentTimers.map((item, index) => (
          <li key={index}>
            {new Date(item.timestamp).toLocaleDateString()} - {new Date(item.timestamp).toLocaleTimeString()} <span className="uk-margin-small-left uk-margin-small-right">|</span>  {item.seconds} Secs.
            <span onClick={this.deleteRecentTimerItem.bind(this, item)} className="uk-float-right" style={{lineHeight: 'normal'}} data-uk-icon="icon: close"></span>
          </li>
        ))
        : <p>No recent timers.</p>;
    }
  }

  render() {
    return (
      <div>
        <hr />
        <div className="uk-card uk-card-default uk-card-body">
          <h3 className="uk-card-title uk-text-center">Recent Timers</h3>
          <ul className="uk-list uk-list-divider">
            { this.renderRecentTimerItems() }
          </ul>
        </div>
      </div>
    )
  }

}

我不知道如何告诉我最近的计时器组件它需要更新,因为新计时器已启动,我想在我最近的计时器列表中找到该计时器。

1 个答案:

答案 0 :(得分:1)

在你的<RecentTimers timer={this.state.timer}>的道具中传递计时器对象this.state.timer可以在你启动计时器时更新,并且只要添加了一个新的计时器,就可以使用componentWillRecieveProps来更新RecentTimer组件的状态在计时器列表中。

每次更新组件后,都会调用函数。

1.componentWillReceiveProps()  
2.shouldComponentUpdate()   
3.componentWillUpdate()  
4.render()  
5.componentDidUpdate()

您可以使用

componentWillReceiveProps(nextProps) {

   if(nextProps.timer){
     let recentTimer = this.state.recentTimers;
     this.setState({
        recentTimers : recentTimers.push(nextProps.timer);// this update your timers, But wont re-render the component.
     });
     //or save the timer 
   }
}

或者使用componentWillUpdate,因为此方法将重新渲染您的组件,

componentWillUpdate(nextProps , nextState){
   //Code goes here.
}

有关状态处理的更多信息,您可以看到此blog

谢谢,