React: Size of components

Posted on June 21st 2020 in React by Pim Debaere.

React: Size of components

After gaining more and more experience using React I created myself a list with best practices. Some of them are based solely on common sense, others are a bit more technical. Today I will write about the size of components.

Avoid components that are too big

To state the obvious, smaller components means code that is easier to read and to maintain. Now it's time to wonder what big and small means in a context like this. In most cases, you can follow your instinct; you just want to avoid duplicate code. In other words, the goal is to have smaller components that you can reuse.

Even when you have certain specific code that can never be reused you should consider refactoring it in smaller components. Having a component with hundreds of lines is harder to maintain and to debug, with the result that each update of that component will take more time than necessary. This is something you want to avoid so you don't drive yourself or your colleagues crazy.

Let's have a look at an example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// index.jsx
import React from 'react'

const data = [
  {
    artist: 'Michael Jackson',
    title: 'Thriller',
    released: '1982'
  },
  {
    artist: 'AC/DC',
    title: 'Back in Black',
    released: '1980'
  },
  {
    artist: 'Meat Loaf',
    title: 'Bat Out of Hell',
    released: '1977'
  },
  {
    artist: 'Pink Floyd',
    title: 'The Dark Side of the Moon',
    released: '1973'
  },
  {
    artist: 'Whitney Houston',
    title: 'The Bodyguard',
    released: '1992'
  }
]

class Albums extends React.Component {
  render() {
    const rows = [];
    
    this.props.albums.forEach((album) => {
      rows.push(
        <tr>
          <td>{album.artist}</td>
          <td>{album.title}</td>
          <td>{album.release}</td>
        </tr>
      )
    });
    
    return (
      <div>
        <form>
          <input type="text" placeholder="Search..." />
          <button>Search album</button>
        </form>
        <table>
          <thead>
            <tr>
              <th>Artist</th>
              <th>Title</th>
              <th>Released in</th>
            </tr>
          </thead>
          <tbody>
            {rows}
          </tbody>
        </table>
      </div>
    )
  }
}

ReactDOM.render(<Albums albums={data} />, document.getElementById('container'));
Fig. 1 – Example of a big component.

After rework (read: refactoring in smaller components) we get the code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// data.js
const data = [
  {
    artist: 'Michael Jackson',
    title: 'Thriller',
    released: '1982'
  },
  {
    artist: 'AC/DC',
    title: 'Back in Black',
    released: '1980'
  },
  {
    artist: 'Meat Loaf',
    title: 'Bat Out of Hell',
    released: '1977'
  },
  {
    artist: 'Pink Floyd',
    title: 'The Dark Side of the Moon',
    released: '1973'
  },
  {
    artist: 'Whitney Houston',
    title: 'The Bodyguard',
    released: '1992'
  }
];

export default data;
Fig. 2 – Refactored data part.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// components/overview.jsx
import React from 'react';

class Overview extends React.Component {
  render() {
    const rows = [];
    
    this.props.albums.forEach((album) => {
      rows.push(
        <tr>
          <td>{album.artist}</td>
          <td>{album.title}</td>
          <td>{album.release}</td>
        </tr>
      )
    });
    
    return (
      <table>
        <thead>
          <tr>
            <th>Artist</th>
            <th>Title</th>
            <th>Released in</th>
          </tr>
        </thead>
        <tbody>
          {rows}
        </tbody>
      </table>
    )
  }
}

export default Overview;
Fig. 3 – Refactored overview part.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// components/search.jsx
import React from 'react';

class Search extends React.Component {
  render() {
    return (
      <form>
        <input type="text" placeholder="Search..." />
        <button>Search album</button>
      </form>
    )
  }
}

export default Search;
Fig. 4 – Refactored search form part.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// components/albums.jsx
import React from 'react';
import Overview from './overview';
import Search from './search';

class Albums extends React.Component {
  render() {
    return (
      <div>
        <Search />
        <Overview albums={this.props.data} />
      </div>
    )
  }
}

export default Albums
Fig. 5 – Refactored Albums part.
1
2
3
4
5
6
// index.jsx
import React from 'react';
import Albums from './components/albums
import data from './data'

ReactDOM.render(<Albums albums={data} />, document.getElementById('container'));
Fig. 6 – The index page after refactoring.

Danger of enthousiasm

The above is a rule of thumb, but don't got too excited either. Of course you can refactor the above example even further, but you also have to wonder if it makes sense to give each HTML element its own component. Then answer is no; you should see a component as a standalone, reusable chunk of HTML. Logical examples of components are a footer, menu, sidebar …

As said in the introduction, this is mainly about gut feeling. Decide for yourself what can be seen as a component for yourself or, if you work in a team, discuss it with each other and make clear agreements. In the end it is you who have to maintain the code, so make it pleasant for yourself.

Be sure to keep an eye on this blog as more React best practices and tips will follow soon.