Introduction to React - React Components

@GoyeSays

Carlos Goyeneche

@GoyeSays

https://github.com/Goye

Doubts or questions about our last talk?

+

Container vs Presentational Components

You’ll find your components much easier to reuse and reason about if you divide them into two categories. I call them Container and Presentational components* but I also heard Fat and Skinny, Smart and Dumb, Stateful and Pure, Screens and Components, etc. These all are not exactly the same, but the core idea is similar.

But...

Props and state

Container vs Presentational Components

Container components

The idea is simple:

A container does data fetching and then renders its corresponding sub-component. That’s it.​

​​

“Corresponding” meaning a component that shares the same name:

StockWidgetContainer => StockWidget
TagCloudContainer => TagCloud
PartyPooperListContainer => PartyPooperList

Why containers?

Container components

class CommentList extends React.Component {
  this.state = { comments: [] };

  componentDidMount() {
    fetchSomeComments(comments =>
      this.setState({ comments: comments }));
  }
  render() {
    return (
      <ul>
        {this.state.comments.map(c => (
          <li>{c.body}—{c.author}</li>
        ))}
      </ul>
    );
  }
}

Few benefits

 

Container components

Reusability

CommentList can’t be reused unless under the exact same circumstances.

Data structure

Your markup components should state expectations of the data they require. PropTypes are great for this.

Once again. This time with a container

class Comments extends React.Component {
  state = { comments: [] };
  componentDidMount() {
    fetchSomeComments(comments =>
      this.setState({ comments: comments }));
  }
  render() {
    return <CommentList comments={this.state.comments} />;
  }
}

Container components

Container components

CommentList component

const CommentList = (props) => {
  return (
    <ul>
      {props.comments.map(c => (
        <li>{c.body}—{c.author}</li>
      ))}
    </ul>
  );
}

So, what did we get?

  • We’ve separated our data-fetching and rendering concerns.
  • We’ve made our CommentList component reusable.
  • We’ve given CommentList the ability to set PropTypes and fail loudly.

We actually got a lot…

Container vs Presentational Components

Container components:

  • Are concerned with how things work.
  • May contain both presentational and container components** inside but usually don’t have any DOM markup of their own except for some wrapping divs, and never have any styles.
  • Provide the data and behavior to presentational or other container components.
  • Call Flux actions and provide these as callbacks to the presentational components.
  • Are often stateful, as they tend to serve as data sources.
  • Are usually generated using higher order components such as connect() from React Redux, createContainer() from Relay, or Container.create() from Flux Utils, rather than written by hand.

Container vs Presentational Components

Presentational components:

  • Are concerned with how things look.
  • May contain both presentational and container components** inside, and usually, have some DOM markup and styles of their own.
  • Often allow containment via this.props.children.
  • Have no dependencies on the rest of the app, such as Flux actions or stores.
  • Don’t specify how the data is loaded or mutated.
  • Receive data and callbacks exclusively via props.
  • Rarely have their own state (when they do, it’s UI state rather than data).
  • Are written as functional components unless they need state, lifecycle hooks, or performance optimizations.

Functional component

import React from 'react';

export default function CommentList(props) {
    return (
        <ul>
            {props.comments.map(c => (
                <li>
                    {c.body}—{c.author}
                </li>
            ))}
        </ul>
    );
}

CommentList.propTypes = {
    comments: React.PropTypes.array.isRequired
};

Stateful and Stateless

Classes and Functions

Components can be declared both as classes and as functions. Functional components are simpler to define but they lack certain features currently available only to class components. Some of these restrictions may go away in the future but they exist today. Because functional components are easier to understand, I suggest you to use them unless you need state, lifecycle hooks, ref, or performance optimizations, which are only available to the class components at this time.

Private Components

var React = require('react');
function FriendItem (props) {
  return <li>{props.friend}</li>
}
function FriendsList (props) {
  return (
    <h1>Friends:</h1>
    <ul>
      {props.friends.map((friend, index) => 
         <FriendItem friend={friend} key={friend} />
      )}
    </ul>
  )
}
module.exports = FriendsList

High Order Components

A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React's compositional nature.

 

Concretely, a higher-order component is a function that takes a component and returns a new component.

High Order Components

Higher Order Components (HOC) are a direct translation of Higher Order Functions from functional languages. A HOC extends the state / behavior of the inner component in a composable way, so you can add many more extensions without the knowledge of the inner component.

High Order Components

What about container component?

High Order Components

import React from 'react';

export default function IfElse({condition, children}) {

    const childrenArray = React.Children.toArray(children);
    const trueChild = childrenArray[0];
    const falseChild = childrenArray[1] || null;

    return condition ? trueChild : falseChild;
}

If-Else Example

High Order Components

import {IfElse} from './if-else';
import {ListOfItems, EmptyList} from './list-components';

class SomeAppComponent extends React.Component {
     // ...
 
     render() {
         const {items} = this.props;
 
         return (
             <IfElse condition={items && items.length > 0}>
                 <ListOfItems items={items}/>
                 <EmptyList message="There are no items in the list"/>
             </IfElse>
         );
     }
 
     // ...
 
}

If-Else Example

Questions?

https://github.com/Goye

Thanks a lot!

https://github.com/Goye

ReactJS Season Components

By Carlos Goyeneche

ReactJS Season Components

ReactJS (Components)

  • 364