@GoyeSays
@GoyeSays
https://github.com/Goye
+
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
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?
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
CommentList can’t be reused unless under the exact same circumstances.
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} />;
}
}
CommentList component
const CommentList = (props) => {
return (
<ul>
{props.comments.map(c => (
<li>{c.body}—{c.author}</li>
))}
</ul>
);
}
We actually got a lot…
Container components:
Presentational components:
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
};
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.
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
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.
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.
What about container component?
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
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
https://github.com/Goye
https://github.com/Goye