Structuring React components
Tags: react, architecture
Published: 2020-05-31 14:58:06

Folder and files structure is something I have found on the matter of the opinion instead of a thing that rules it all.

Depending of the project there is minimal convention on how components are structured inside a project (spoiler alert, inside `/components` folder and separation of container/UI components). 

This time, I want to go to the space on **how to structure a component** itself.

I have created an opinion after working with several mid sized code bases.

## TL;DR:

```
component-name/
├── index.js/ts
├── component-name.js/ts
├── styled-components.js/ts
├── component-name.test.js/ts 
├── component-name.mapping.js/ts 
```

## Files, camelCase or kebab-case?

I use kebab-case naming style, GitHub by default is case insensitive, that means that changing HolaFolder to holafolder [is not an actual change that it will recognise](https://stackoverflow.com/questions/6899582/i-change-the-capitalization-of-a-directory-and-git-doesnt-seem-to-pick-up-on-it).

Also it's simpler to read by having one character that separates the world instead the cognitive load of capital letters vs lowercase ones.

## The index file

This is the file that I use to expose the component.

Let's imagine that I have simple UI component that exports default.

``` js
// index.js/ts
export { default } from './example-component'
```

Or in the case of named exports:

``` js
// index.js/ts
export { openModal, closeModal } from './example-component'
```

We don't need to change the imports of any component in which we use the 'example-component'.

## Implementation details, in the component-name.js/ts file

I have seen a lot a structure like this:
```
component-name/
├── index.js
```

In which `index.js` has the implementation details of our component, the problem. While working and having 10+ tabs with the same name makes difficult to follow the file that I want to find.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cn5wh83vrns9xmatl7t9.png)

For that reason I add the implementation on a file with the same name as the components' folder, to make easier to work with multiple files.

## styled-components.js/ts

This is based on the fact that the last 3 years of my career I have been working in companies that used it.

Having a separated file for the components which responsibility is purely aesthetics make easier for:
- A designer that codes to tweak the components without the need to change the implementation file
- A developer to separate the concern of your components
- Insolate styles in a common pattern file which makes it easier to identify project wide

## Tests

Having `component-name.test.js/ts` is a common pattern, the difference is that I prefer to have the tests as close as the implementation, this so if the component is obsolete and we need to remove it, we remove it as a module, the contrary of having a [special folder tree for tests](http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html), which can lead to broken (unused files).

## Mapping and (component-name.***.js/ts)

[Redux](https://redux.js.org/) is a common library used for state management, but nowadays we have different solutions, and what we do is to "connect", or "map" certain props in our component to a store.

For that reason we created the `component-name.mapping.js/ts` component.

``` js
// mapping component
const mapStateToProps = () => {}
const mapDispatchToProps = () => {}

export default connect(mapStateToProps, mapDispatchToProps)(Component)
```

In that sense if we have a component that in the future needs to be connected and we have the `index.js` file that exposes our component, then is as easy to change it to:
```
export { default } from './component-name.mapping'
```

And not other components need to be changed.

## Wrapping up

- `index.js/ts`: to expose the component
- `component-name.js/ts`: components implementation
- `styled-components.js/ts`: styled component (thanks capitan obvious)
- `component-name.test.js/ts`: tests
- `component-name.mapping.js/ts`: HOC or implementation to connect a component to a store