DEV Community

loading...
Cover image for Presentational and Container Components in React

Presentational and Container Components in React

olenadrugalya profile image Olena Drugalya ・3 min read

This blogpost continues series of posts exploring React components. It describes 2 types of components - Presentational and Container - together, because they can be better understood as a couple :)

Before we start exploring them, we need to understand 2 things:

  1. These 2 types does NOT extend React.Component base class. There is NO such type as PresentationalComponent or Container. It's more like a convention or pattern, which developers use while building applications with React.

  2. This pair can be called stateless and stateful or impure and pure, but this is NOT the same. Presentational components can be stateful, and containers can be stateless too, or they can be pure functional components or pure class-based components.

Introduction and Overview

As was mentioned above, the devision to Presentational and Container components is a development pattern, used by developers to distinct components by their purpose:

  • presentational components takes care of how things look
  • container component takes care of how things work

Main features of Presentational Component

  • their main function is to display the data;
  • they usually contain just render() method or just JSX;
  • they can have their own styles;
  • they rarely have their own state (when they do, it’s UI state rather than data);
  • they don't know how to change/mutate data;
  • they receive data via props from container component;
  • they usually are written as stateless function components (though this is not a rule)

Example:

const Book = ({ title, img_url }) => (
  <div className="book">
    <img src={ img_url } alt={title}/>
    <h3>{ title }</h3>
  </div>
)
export default Book;
Enter fullscreen mode Exit fullscreen mode

The above example has only one task to do - render given props of title and img_url to the DOM.

Lists are also examples of presentational component since all what they really do is to define how to display list of components and to pass data via props to those components.

Example:

import Book from './Book';

const BookList = ({ books }) => (
  <div className="book-list">
    { books.map(book => <Book title={book.title} img_url={book.img_url} />) }
  </div>
)

export default BookList;
Enter fullscreen mode Exit fullscreen mode

Presentational components get their data from container components, and if we look at relations between them, it's child-parent relation mostly, where presentational components represents children and container components are in almost every case parents of presentational components.

Main features of Container Component

  • their main function is organise the behaviour of data
  • they contain more elements together with render() function (other presentational components, lifecycle methods or hooks);
  • they don't have their own styles;
  • they have state and manage it;
  • they provide data and behaviour to children components;
  • they usually are written as class-based stateful components (even though nowadays its a tendency to use hooks, so most often they are written as functional stateful components)

Example (class-based):

import BookList from './BookList'

class BookList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      books: []
    };
  }

  componentDidMount() {
    fetch('https://learn-co-curriculum.github.io/books-json-example-api/books.json')
      .then(response => response.json())
      .then(bookData => this.setState({ books: bookData.books }))
  }

  render() {
    return <BookList books={this.state.books} />
  }
}
export default BookListContainer;
Enter fullscreen mode Exit fullscreen mode

Example (functional):

import BookList from './BookList';
import {useState, useEffect} from 'react';

const BookList = () => {

const [books, setBooks] = useState([]);

useEffect(() => {
  fetch('https://learn-co-curriculum.github.io/books-json-example-api/books.json')
      .then(response => response.json())
      .then(bookData => setBooks({bookData.books}) }, []);
  }

  render() {
    return <BookList books={books} />
  }
}
export default BookListContainer;
Enter fullscreen mode Exit fullscreen mode

Conclusion

These 2 types of components are always go together as they share the same pattern. Since React is constantly evolving, it's possible to write React applications using functional components and hooks ONLY, since they can solve most of problems now. Separation of concerns between presentation and logic is a good way to better understand how your app should work and what UI it will have. But this pattern is NOT a must and you can use it if you find it natural for your application.

Thank you for reading my blog. Feel free to connect on LinkedIn or Twitter :)

Buy Me a Coffee at ko-fi.com

Discussion (0)

pic
Editor guide