1
\$\begingroup\$

This is a ReactJS component that accepts a date and displays how long ago this date was (5 seconds ago, 3 minutes ago, 5 hours ago, ...) + it uses a setTimeout to automatically update itself when the state.displayDate changes.

What's going on:

  • On ComponentWillMount: set state.date from props
  • Update the state.displayDate with a setTimeout

Is this a good pattern or what are the alternatives?

var MomentAgo = React.createClass({
  propTypes: {
    date: React.PropTypes.string.isRequired
  },
  getInitialState: function() {
    return {
      date: null,
      displayDate: null
    };
  },
  componentWillMount: function (){
    this.setState({ date: this.props.date });
  },
  componentDidMount: function() {
    //with a setTimeout:
    this.setState({ displayDate: date.format('DD MMMM YYYY') });
  },
  render: function() {
    return(<span>{this.state.displayDate}</span>);    
  }

According to Facebook, setting initial state from props is an anti-pattern. What happens here is that state is set from props in ComponentWillMount. It would seem that this is thus also the same anti-pattern. Or is this the correct way to do it?

\$\endgroup\$
3
  • \$\begingroup\$ Welcome to CodeReview, Laoujin. Would you add some more context to your code? State its purpose, and exactly what you'd like to focus on in the program. \$\endgroup\$
    – Legato
    Commented Apr 23, 2015 at 12:26
  • \$\begingroup\$ I trimmed it down considerably because I'm confused about the whole state vs props thing. Should I post the code for the entire jsx? \$\endgroup\$
    – Laoujin
    Commented Apr 23, 2015 at 13:06
  • \$\begingroup\$ I'm a total React noob still but I would guess that the anti-pattern stuff somehow relates to an opinion that props should be immutable and copying them into state implies that they aren't, and perhaps that state should be separate from your props (i.e., other stuff should change, not the stuff that depends on props). Just a hunch though that "feels" right intuitively for me... \$\endgroup\$
    – Josh
    Commented Jun 17, 2015 at 0:47

1 Answer 1

2
\$\begingroup\$

In order to keep to the React pattern and stick to immutability of props simply separate your code to have a parent component which carries out the logic and passes the the date to the child component which can then be displayed in the child's render component.

It would then look something like this:

var React = require('React');

var MomentDisplay = React.createClass({
    propTypes: {
        date: React.PropTypes.string.isRequired
    },
    render: function() {
        return (
            <span>
                {this.props.displayDate}
            </span>
        )
    }
});

var MomentAgo = React.createClass({
    getInitialState: function () {
        return {
            date: null,
            displayDate: null
        };
    },
    componentWillMount: function () {
        this.setState({date: this.props.date});
    },
    componentDidMount: function () {
        setTimeout(function(){
            this.setState({displayDate: date.format('DD MMMM YYYY')});
        }, 3000);
    },
    render: function () {
        return (
            <MomentDisplay displayDate={this.state.displayDate} />
            )
        }
});
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.