2017-07-02 111 views
0

如何正確刷新moment.from()。我在componentDidMount中嘗試set setInterval(this.renderReminders(),1000),但不起作用,彈出錯誤。如何解決這個問題?Rerender moment.fromNow()在React

class App extends Component { 
 

 
renderReminders() { 
 
    const { reminders } = this.props; 
 
    return (
 
     <ListGroup> 
 
     { 
 
      reminders.map(reminder => { 
 
      return (
 
       <ListGroupItem key={reminder.id}>    
 
       <div>{moment(reminder.dueDate, 'DD-MM-YYYY HH:mm').fromNow()}</div>    
 
       </ListGroupItem> 
 
      ) // return 
 
      }) // reminders.map 
 
     } 
 
     </ListGroup> 
 
    ) // return 
 
    } // renderReminders() 
 
    
 
    render() { 
 
    return (
 
     <div className="container">  
 
     { this.renderReminders() } 
 
     </div> 
 
    ) // return 
 
    } // render 
 
    
 
} // App

+0

你得到什麼錯誤,當你把它放在componentDidMount? –

+0

看看這個類似的帖子與解決方案幫助:https://stackoverflow.com/questions/36299174/setinterval-in-a-react-app – terpinmd

回答

2

我想說有很多方法可以在React中製作計時器。
一個建議是推斷提醒到另一個反應組件。

在新組件的狀態中設置reminderTime,然後創建一個使用this.setState來更新計時器的方法。

如果狀態發生變化,setState將自動重新渲染組件。

在componentWillMount中,您應該使用setInterval來調用將更新狀態的函數。在componentWillUnmount中,您應該刪除clearInterval的時間間隔。

我沒有測試下面的代碼,所以它主要是爲了得到這個想法。

class Reminder extends React.Component{ 
 
    constructor(props){ 
 
     super(props); 
 
     this.state = { 
 
      reminderTime : moment(this.props.dueDate, 'DD-MM-YYYY HH:mm').fromNow()}, 
 
     } 
 
    } 
 

 
    componentDidMount(){ 
 
     // add the interval 
 
     this.interval = setInterval(this.updateReminderTime.bind(this), 3000); 
 
    } 
 

 
    componentWillUnmount(){ 
 
     // remove the interval listener 
 
     clearInterval(this.interval); 
 
    } 
 

 
    updateReminderTime(){ 
 
    this.setState({ 
 
     reminderTime : moment(this.props.dueDate, 'DD-MM-YYYY HH:mm').fromNow()} 
 
    } 
 
    
 
    render(){ 
 
     return <div>{this.state.reminderTime }</div> 
 
    } 
 
} 
 

 
class App extends Component { 
 
renderReminders() { 
 
    return (
 
     const reminders = this.props.reminders; 
 
     <ListGroup> 
 
     { 
 
      reminders.map(reminder => { 
 
      return (
 
       <ListGroupItem key={reminder.id}>    
 
       <Reminder dueDate={reminder.dueDate} />    
 
       </ListGroupItem> 
 
      ) // return 
 
      }) // reminders.map 
 
     } 
 
     </ListGroup> 
 
    ) // return 
 
    } // renderReminders() 
 
    
 
    render() { 
 
    return (
 
     <div className="container">  
 
     { this.renderReminders() } 
 
     </div> 
 
    ) // return 
 
    } // render 
 
    
 
} // App

+0

優秀的工作。 –

+0

我可以問一下嗎?爲什麼你使用...綁定(這)...我百倍地閱讀(與上下文有關的東西),雖然我無法正確理解它 –

1

而不是使用一個組件以使多個計時器的,我想你應該創建一個組件以使1個計時器,然後重新使用它爲所有的情況下(通過定時器作爲支持它)。

下面是一個基本的例子。

class App extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = {date: moment().format('DD-MM-YYYY HH:mm').fromNow()}; 
    } 

    componentDidMount() { 
    this.timerID = setInterval(
    () => this.tick(), 
     1000 
    ); 
    } 

    componentWillUnmount() { 
    clearInterval(this.timerID); 
    } 

    tick() { 
    this.setState({ 
     date: moment().format('DD-MM-YYYY HH:mm').fromNow() 
    }); 
    } 

    render() { 
    return (
     <div> 
     date={this.state.date} 
     </div> 
    ); 
    } 
} 

現在你只需要通過初始日期作爲道具,並重新使用該組件爲所有的定時器。

0

你應該保持剩餘時間的狀態,用setInterval來定期更新(遞減)狀態的那部分。然後這個狀態更新將觸發你的組件的渲染。

1

const {ListGroup, ListGroupItem} = Reactstrap; 
 

 
class App extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 
    
 
    this.state = { 
 
     interval: null, 
 
     reminders: this.nextReminders(props.reminders), 
 
    }; 
 
    
 
    this.refreshReminders = this.refreshReminders.bind(this); 
 
    this.nextReminders = this.nextReminders.bind(this); 
 
    } 
 
    
 
    componentDidMount() { 
 
    const interval = setInterval(this.refreshReminders, 1000); 
 
    this.setState({ interval }); 
 
    } 
 
    
 
    componentWillUnmount() { 
 
    const { interval } = this.state; 
 
    clearInterval(interval); 
 
    } 
 
    
 
    refreshReminders() { 
 
    const { reminders } = this.props; 
 
    const nextReminders = this.nextReminders(reminders); 
 
    
 
    this.setState({ reminders: nextReminders }); 
 
    
 
    console.log('refresh !'); 
 
    } 
 
    
 
    nextReminders(reminders) { 
 
    return reminders.map(reminder => { 
 
     return { 
 
     ...reminder, 
 
     render: moment(reminder.dueDate, 'DD-MM-YYYY HH:mm').fromNow() 
 
     }; 
 
    }); 
 
    } 
 
    
 
    renderReminders() { 
 
    const { reminders } = this.state; 
 
    
 
    return (
 
     <ListGroup> 
 
     { 
 
      reminders.map(reminder => { 
 
      return (
 
       <ListGroupItem key={reminder.id}>    
 
       <div>{reminder.render}</div>    
 
       </ListGroupItem> 
 
      ) // return 
 
      }) // reminders.map 
 
     } 
 
     </ListGroup> 
 
    ) // return 
 
    } // renderReminders() 
 
    
 
    render() { 
 
    return (
 
     <div className="container">  
 
     { this.renderReminders() } 
 
     </div> 
 
    ) // return 
 
    } // render 
 
    
 
} // App 
 
    
 
const data = [ 
 
    {id: 1, dueDate: '02-07-2017 15:34'}, 
 
    {id: 2, dueDate: '02-07-2017 13:00'}, 
 
    {id: 3, dueDate: '02-07-2017 14:00'}, 
 
]; 
 
    
 
ReactDOM.render(<App reminders={data} />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> 
 
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/> 
 
<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> 
 
<script src="https://unpkg.com/reactstrap/dist/reactstrap.min.js"></script> 
 

 
<div id="app"></div>