The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

tempusfugit (144) [Avatar] Offline
#1
FYI

Judicious use of non-in-line arrow functions,
  • Spread operator in object literals (ES2018)
  • Shorthand property names (ES2015)
  • Destructuring (ES2015)
  • can cut down on the noise quite a bit.

    Example:
    // i.e. CommentBox.js aka "module CommentBox"
    
    const commentsUpdate = (comments, newComment) => ({
      comments: comments.concat([newComment])
    });
    
    const postElement = (post) =>
      React.createElement(Post, { ...post }); // spread operator in object literal
    
    const commentElement = (comment) =>
      React.createElement(Comment, { key: comment.id, ...comment });
    
    class CommentBox extends Component {
      constructor(props) {
        super(props);
        this.state = { comments: this.props.comments };
      }
    
      handleCommentSubmit = (comment) => {
        comment.id = Date.now();
        this.setState(commentsUpdate(this.state.comments, comment));
      };
    
      render() {
        const onCommentSubmit = this.handleCommentSubmit;
    
        return React.createElement(
          'div',
          { className: 'commentBox' },
          postElement(this.props.post),
          this.state.comments.map(commentElement),
          React.createElement(CreateComment, { onCommentSubmit }) // shorthand property name
        );
      }
    }
    CommentBox.propTypes = {
      post: PropTypes.object,
      comments: PropTypes.arrayOf(PropTypes.object)
    };
    
    // export default CommentBox;
    
    JSX example: Listing 2.11 Rewriting components using JSX
    // ...
    class Post extends Component {
      render() {
        const {user, content, children} = this.props;
    
        return <div className="post">
          <h2 className="postAuthor">{user}</h2>
          <span className="postBody">{content}</span>
          {children}
        </div>;
      }
    }
    Post.propTypes = {
      user: PropTypes.string.isRequired,
      content: PropTypes.string.isRequired,
      id: PropTypes.number.isRequired
    };
    
    class Comment extends Component {
      render() {
        const {user, content} = this.props;
    
        return <div className="comment">
          <h2 className="commentAuthor">{user + " : "}</h2>
          <span className="commentContent">{content}</span>
        </div>;
      }
    }
    Comment.propTypes = {
      id: PropTypes.number.isRequired,
      content: PropTypes.string.isRequired,
      user: PropTypes.string.isRequired
    };
    
    // i.e. CreateComment.js aka "module CreateComment"
    
    const initialState = () => ({
      content: '',
      user: ''
    });
    
    const prepareComment = ({user, content}) =>({
      user: user.trim(),
      content: content.trim()
    });
    
    class CreateComment extends Component {
      constructor(props) {
        super(props);
        this.state = initialState();
      }
    
      handleUserChange = ({target: {value: user}}) => {
        this.setState(() => ({ user }));
      };
    
      handleContentChange = ({target: {value: content}}) => {
        this.setState(() => ({ content }));
      };
    
      handleSubmit = (event) => {
        const { onCommentSubmit } = this.props;
    
        event.preventDefault();
        onCommentSubmit(prepareComment(this.state));
        this.setState(initialState);
      };
    
      render() {
        const {user, content} = this.state;
    
        return <form {...{
            className: 'createComment',
            onSubmit: this.handleSubmit
          }}>
          <input {...{
            type: 'text',
            placeholder: 'Your name',
            value: user,
            onChange: this.handleUserChange
          }} />
          <input {...{
            type: 'text',
            placeHolder: 'Thoughts?',
            value: content,
            onChange: this.handleContentChange
          }} />
          <button type="submit">Post</button>
        </form>;
      }
    }
    CreateComment.propTypes = {
      onCommentSubmit: PropTypes.func.isRequired,
      content: PropTypes.string
    };
    // export default CreateComment;
    
    // i.e. CommentBox.js aka "module CommentBox"
    
    const commentsUpdate = (comments, newComment) => ({
      comments: comments.concat([newComment])
    });
    
    const commentElement = (comment) =>
      <Comment {...{key: comment.id, ...comment}} />;
    
    class CommentBox extends Component {
      constructor(props) {
        super(props);
        const { comments } = this.props;
        this.state = { comments };
      }
    
      handleCommentSubmit = (comment) => {
        const { comments } = this.state;
        comment.id = Date.now();
        this.setState(commentsUpdate(comments, comment));
      };
    
      render() {
        const { post } = this.props;
        const { comments } = this.state;
        const onCommentSubmit = this.handleCommentSubmit;
    
        return <div className="commentBox">
          <Post {...post} />
          {comments.map(commentElement)}
          <CreateComment {...{onCommentSubmit}} />
        </div>;
      }
    }
    CommentBox.propTypes = {
      post: PropTypes.object,
      comments: PropTypes.arrayOf(PropTypes.object)
    };
    
    // export default CommentBox;
    
    render(<CommentBox {...data} />, node);
    
    All of this works with the standard transpilation pipeline set up with create-react-app.