在React中重新渲染moment.fromNow()

时间:2017-07-02 12:23:01

标签: javascript reactjs redux

如何正确刷新moment.from()。我尝试在componentDidMount中设置setInterval(this.renderReminders(),1000),但是不起作用,弹出错误。如何解决这个问题?

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

6 个答案:

答案 0 :(得分:3)

我说在React中有很多方法可以制作计时器 一个建议是将Reminder推断为另一个反应组件。

在新组件的状态中设置reminderTime,然后创建一个使用this.setState更新计时器的方法。

如果状态发生变化,setState将自动重新渲染组件。

在componentWillMount中,您应该使用setInterval来调用将更新状态的函数。在componentWillUnmount中,你应该摆脱clearInterval的间隔。

我没有测试下面的代码,所以主要是为了得到这个想法。

&#13;
&#13;
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
&#13;
&#13;
&#13;

答案 1 :(得分:2)

我认为您不应该使用一个组件来渲染多个计时器,而是应该创建一个组件来渲染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>
    );
  }
}

现在您只需将初始日期作为道具传递,并为所有计时器重复使用此组件。

答案 2 :(得分:2)

我知道我要晚发布此消息,但是它可以帮助其他刚接触此问题的人。

最好使用轻松的反应片刻

要求; 时刻,反应片刻

import React from 'react'
import Moment from 'react-moment'

const UpdatesTheTime = () => {
    return (
        <Moment interval={1000} fromNow>
            {reminder.dueDate}
        </Moment>
    )
}

export default UpdatesTheTime

当我将时间间隔设置为1000时,它将每秒更新一次

要查看结果,请观看1分钟标记后的变化

我使用时间戳记,例如1590115433736作为时间值,并且效果很好

有关更多信息,请参见https://openbase.io/js/react-moment

解析格式可用于您的时间值。

示例

答案 3 :(得分: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>

答案 4 :(得分:1)

这是我使用钩子制成的组件。

import moment from "moment";
import React, { useEffect, useState } from "react";

const formatter = (timestamp) => {
  return moment.unix(timestamp).fromNow();
};

export default ({ timestamp, interval }) => {
  const [timestampString, setTimestampString] = useState("");

  useEffect(() => {
    const timer = setInterval(
      () => setTimestampString(formatter(timestamp)),
      interval
    );
    setTimestampString(formatter(timestamp));
    return () => clearInterval(timer);
  }, []);
  return timestampString;
};

它可以用作:

<ReactMoment timestamp={1597213985} interval={1000} />

它每1秒钟更新一次时刻。

答案 5 :(得分:0)

您应该将时间保持在状态,并使用setInterval定期更新(递减)该部分状态。然后,此状态更新将依次触发组件的渲染。