2017-07-05 1 views
0

私は反応で簡単なタイマーアプリを作成しました。これはあなたが数字を入力してカウントダウンを開始できるようにします。私は、設定されたタイマーを保存するAPIを実装しました。それらはcomponentDidMountで読み込まれます。ボタンを使って1つずつ削除することができます。問題:タイマーの起動が別のコンポーネントにあり、 "RecentTimers"コンポーネントの状態が分からない。私は反応でこれを正しく行う方法がわからない。 私の最初のReactJSアプリでこれを進める方法がわからない

この

は、実際のタイマーを気コンポーネントです:

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

<RecentTimers timer={this.state.timer}>の小道具にthis.state.timerを渡すことができます。タイマーを開始するときはいつでも更新し、timerに新しいタイマーが追加されるたびにComponentWillRecievePropsを使用してRecentTimerコンポーネントの状態を更新できますリスト。

コンポーネントを更新するときはいつでも、次の関数が呼び出されます。

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

あなたは、状態の取り扱いの詳細は、このblogを見ることができます

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. 
} 

を使用することができます。

ありがとう、

+0

Thx、私はすでにこのようなものを考えました。そんなに悪い練習ではないですか?私はできるだけ早くそれを試みます。 – SVARTBERG

+0

はい、この[記事](https://medium.com/react-ecosystem/how-to-handle-state-in-react-6f2d3cd73a0c)を見ることができます。これは、反応状態の生態系をよく理解しています。 –

+0

事は、それが新しいタイマーであるかどうかをどのように識別するのですか?タイマーコンポーネントでtick()関数を見ることができます。プログレスバーが1秒減少するたびに呼び出されます。したがって、ComponentTrackerコンポーネントのcomponentWillReceiveProps()は、タイマーが1秒おきにTimerコンポーネントの状態を受け取ることになります。残りの秒を除いて、状態のすべてが同じになります。新しいタイマーが開始されたことをどのように識別すべきですか? より良いトリガーは、TimerコンポーネントのstartTimer()関数です。その関数が呼び出されるたびに、ニュースタイマーエントリがAPIを介して追加されます – SVARTBERG

関連する問題