/* Good practices: - name CSS classNamees like the associated component - prefix non-React method names by an "_" - pass a "key" attribute to elements in a loop State - direct reads, write through setState() - declare initial state in constructor() - setState() calls render(): beware loops = avoid it in render() Refs: - are called by React during render() - (foo) => { this._bar = foo; ) translates to function(foo) { this._bar = foo; }.bind(this); Events: - React events are "synthetic" events, masking the browser behaviour differences - https://facebook.github.io/react/docs/events.html Lifecycle methods: - Main: componentWillMount / componentDidMount / componentWillUnmount - fetch initial data from cWM, start a refresh poll loop from cDM, stop loop from cWU - https://facebook.github.io/react/docs/react-component.html JSX: - "className", not "class" - knows how to render an array of JSX elements, not just one. */ class Comment extends React.Component { render() { return (
); } } class CommentForm extends React.Component { _handleSubmit(event) { // Prevent the page from reloading. event.preventDefault(); // this._author/this._body are populated by refs in JSX let author = this._author; let body = this._body; // Since they are elements, we need to take their ".value". this.props.addComment(author.value, body.value); // addComment is called on this.props, meaning it is passed by component parent. } render() { return ( ); } } class CommentBox extends React.Component { constructor() { super(); this.state = { showComments: false, comments: [] }; } _addComment(author, body) { const comment = { id: this.state.comments.length + 1, author, body }; // concat(), not push(): push() mutates the data, concat doesn't. // By allocating a new reference, for comments, React detects the change fast. this.setState({comments: this.state.comments.concat([comment])}); } _fetchComments() { jQuery.ajax({ method: "GET", url: "/static/comments.json", // Arrow function: keep "this" binding to the class instance. success: (comments) => { this.setState({comments}); } }); } _getComments() { return this.state.comments.map((comment) => { return (