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