mantrajs / mantra-sample-blog-app

A sample blog app built with Mantra
http://mantra-sample-blog-app.herokuapp.com/
MIT License
296 stars 104 forks source link

Component declaration variations #77

Closed purplecones closed 8 years ago

purplecones commented 8 years ago

I'm still trying to wrap my head around Mantra and the new React syntax with ES2015. What's the difference between these components? Why is one declared normally with extends React.Component and the other is not.

mantra-sample-blog-app/client/modules/core/components/newpost.jsx

import React from 'react';

class NewPost extends React.Component {
  render() {
    const {error} = this.props;
    return (
      <form className="new-post" onSubmit={this.createPost.bind(this)}>
        <h2>Add New Post</h2>
        {error ? <p style={{color: 'red'}}>{error}</p> : null}

        <input ref="titleRef" type="Text" placeholder="Enter your post title." /> <br/>
        <textarea ref="contentRef" placeholder="Enter your post content." /> <br/>
        <button type="submit">Add New</button>
      </form>
    );
  }

  createPost(event) {
    // Becaus the test cannot get event argument
    // so call preventDefault() on undefined cause an error
    if (event && event.preventDefault) {
      event.preventDefault();
    }

    const {create} = this.props;
    const {titleRef, contentRef} = this.refs;

    create(titleRef.value, contentRef.value);
  }
}

export default NewPost;

mantra-sample-blog-app/client/modules/core/components/postlist.jsx

import React from 'react';

const PostList = ({posts}) => (
  <div className='postlist'>
    <ul>
      {posts.map(post => (
        <li key={post._id}>
          <a href={`/post/${post._id}`}>{post.title}</a>
        </li>
      ))}
    </ul>
  </div>
);

export default PostList;
Rayman commented 8 years ago

Quote: You may also define your React classes as a plain JavaScript function: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions

discdiver commented 8 years ago

const PostList = ({posts}) => ( ......... )

is the syntax for a stateless functional component. It doesn't allow you to do as much as creating a React component object of type class, but it saves keystrokes and React may optimize for it in the future.

From the React blog: https://facebook.github.io/react/blog/2015/10/07/react-v0.14.html

Stateless functional components In idiomatic React code, most of the components you write will be stateless, simply composing other components. We’re introducing a new, simpler syntax for these components where you can take props as an argument and return the element you want to render:

// A functional component using an ES2015 (ES6) arrow function:
var Aquarium = (props) => {
  var fish = getFish(props.species);
  return <Tank>{fish}</Tank>;
};

// Or with destructuring and an implicit return, simply:
var Aquarium = ({species}) => (
  <Tank>
    {getFish(species)}
  </Tank>
);

// Then use: <Aquarium species="rainbowfish" />

These components behave just like a React class with only a render method defined. Since no component instance is created for a functional component, any ref added to one will evaluate to null. Functional components do not have lifecycle methods, but you can set .propTypes and .defaultProps as properties on the function.

This pattern is designed to encourage the creation of these simple components that should comprise large portions of your apps. In the future, we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.

purplecones commented 8 years ago

I see. Thanks for the clarification!