/* 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 constructo() 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 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: [ { id: 1, author: "Morgan McCircuit", body: "great picture!" }, { id: 2, author: "Bending Bender", body: "Excellent stuff" } ] }; } _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])}); } _getComments() { return this.state.comments.map((comment) => { return (