Search code examples
javascriptreactjsreact-bootstrap-table

How do I display countdowns in a column of a react-bootstrap-table-next table?


I currently have a column in a react-bootstrap-table-next table that displays an expiration date. Here's how I define the column:

    const columns = [{
      ...
    }, {
      dataField: 'expiresAt',
      text: 'Expires',
      formatter: timestampFormatter
    }];

(I replaced the other columns with ... for brevity.)

And here's the timestampFormatter function:

    function timestampFormatter(cell, row) {
      if (cell == null) {
        return cell;
      } else {
        return (moment(cell).utcOffset(cell).local().format('llll'));
      }
    }

Here's an example of what one cell in this column looks like now:

enter image description here

I'd like to replace these cells with a countdown that shows the number of days, hours, and minutes (and seconds if less than a minute is left) until expiry. I can certainly write the code to create a string with this. But I don't see how to get the cells in this column to update every second.

I could replace timestampFormatter with something like this:

    function countdownFormatter(cell, row) {
      return (
        <Countdown expires={cell} />
      );
    }

...and calculate the countdown string inside the Countdown component's render method. But since the components' props would never change, they wouldn't re-render.

I could do something like this:

    function countdownFormatter(cell, row) {
      countdownString = countdownFromExpiration(cell);
      return (
        <Countdown countdown={countdownString} />
      );
    }

But then I don't see how to arrange the countdownFormatter functions to all get called every second.


Solution

  • Code Maniac's comment on my question suggesting using setTimeOut gave me what I needed to figure the rest out for myself. I did create a Countdown component as I considered in my question. Here's the code I came up with:

    class Countdown extends Component {
      state = {
        timeRemainingString: getTimeRemainingString(this.props.expires)
      };
    
      componentDidMount() {
        this.updateState();
      }
    
      updateState() {
        this.setState({ timeRemainingString:
                        getTimeRemainingString(this.props.expires) });
        this.timeout = setTimeout(() => { this.updateState() }, 1000);
      }
    
      componentWillUnmount() {
        clearTimeout(this.timeout);
      };
    
      render() {
        return ( this.state.timeRemainingString );
      }
    }