• Stars
    star
    155
  • Rank 235,613 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 7 years ago
  • Updated 12 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Our React Style Guide

React Code Style Guide

Our React projects' best practices


Introduction

This is meant to be a guide to help new developers understand the React code style and best practices we adopt here at Pagar.me.

As this guide is an extension of our JavaScript style guide, we highly recommend reading it before you continue.

Installing

The rules described in this repository are also available as a NPM package. To install the package and its dependencies:

$ npm install --save-dev [email protected] \
                         eslint-config-pagarme-react \
                         [email protected] \
                         stylelint-config-pagarme-react \

The peer dependencies specified above have hardcoded versions. If you prefer, you can use the command npm info eslint-config-pagarme-react@latest peerDependencies to find the exact peer dependencies to install.

To include these rules into your project, create the following config files in your root folder:

.eslintrc

{
  "extends": ["pagarme-react"],
  "env": {
    "browser": true
  }
}

.stylelintrc

{
  "extends": ["stylelint-config-pagarme-react"]
}

Table of contents

Component definition

All components (presentation, containers or pages) should always be defined as a directory, named with pascal casing. The main component file should be index.js, main stylesheet style.css. CSS custom properties can be kept in properties.css:

AwesomeCard/
├── index.js
├── properties.css
└── style.css
  • Styles should always be defined in a separate CSS file
  • Avoid prefixing or suffixing component names
    • E.g.: lib/pages/UserPage or lib/container/UserContainer
  • On conflict rename on import time
    • import UserContainer from '...'  - import { User as UserContainer } from '...'

⬆️ Back to top

Project organization

Your project components should be separated in at least three directories:

awesome-react-project/
└── src/
   ├── components/
   ├── containers/
   └── pages/

Each of these directories have special types of components:

components/

Stateless components. Shouldn't store state. Most components in this directory will be function-based components. Stuff like buttons, inputs, labels and all presentational components goes here. This components can also accept functions as props and dispatch events, but no state should be held inside.

containers/

Container components can store state. Containers are built mostly from the composition of presentational components with some styles to layout them together. Containers can also store internal state and access refs to provide additional logic, but all actions should be accepted as component callbacks.

pages/

Page components can store state, receive route parameters and dispatch Redux actions when applicable. Pages are the highest level of application's components. They represent the application routes and most times are displayed by a router. Pages are also responsible for handling container components callbacks and flowing data into children containers.

⬆️ Back to top

Code standards

Destruct your props

More than 2 props from an object been used in the same place should be destructed

Code style

Line length should not exceed 80 characters.

Use explanatory variables

Bad

const onlyNumbersRegex = /^\d+$/
const validateNumber = message => value => !onlyNumbersRegex.test(value) && message

validateNumber('error message')(1)

Good

const onlyNumbersRegex = /^\d+$/
const getNumberValidation = message => value => !onlyNumbersRegex.test(value) && message

const isNumber = getNumberValidation('error message')

isNumber(1)

Use searchable names

Bad

setTimeout(doSomething, 86400000)

Good

const DAY_IN_MILLISECONDS = 86400000

setTimeout(doSomething, DAY_IN_MILLISECONDS)

Naming

Test files must start with the class which will be tested followed by .test.

Class and components folders names must start with capital letter.

React peculiarities

Never "promisify" the setState

It's a small anti-pattern which can cause some problems in the component lifecicle. You can found more arguments about this in this issue

Mixins

Why? Mixins introduce implicit dependencies, cause name clashes, and cause snowballing complexity. Most use cases for mixins can be accomplished in better ways via components, higher-order components, or utility modules.

Components

One line props when are more than 2 or big props

Bad

<button type="submit" disabled onClick={() => null} className="aLongSpecificClassName">
  Click here
</button>

<button type="submit" className="aLongSpecificClassName">
  Click here
</button>

<button className="aLongSpecificClassName">Click here</button>

Good

<button
  className="aLongSpecificClassNameWithLasers"
  disabled={loading}
  onClick={() => null}
  type="submit"
>
  Click here
</button>

One line component

Bad

<div className="example"><span class="highlight">Bad</span> example</div>

Good

<div className="example">
  <span className="highlight">Bad</span>
  example
</div>

CSS are modules!

We use CSS modules everywhere. CSS modules are great because they provide scope to CSS and allow us to create compartmentalized styles that don't leak to global scope. Here are our good practices of doing CSS modules:

Formatting CSS

80 columns, soft tabs of 2 spaces

Keep your code lines under 80 columns wide. This helps when opening multiple splits. Use soft tabs of 2 spaces to save some space! 😛

Camel case instead of dash-case for class names

With CSS modules, camel case makes much more sense:

GOOD
lib/components/Input/index.js lib/components/Input/style.css
import style from './style.css'

const Item = ({ children }) =>
  <li className={style.circleBullet}>
    {children}
  </li>

export default Item
.circleBullet {
  list-style-type: disc;
}

⬆️ Back to top

Never use ID and tag name as root selectors!

Using ID and tag name at the selector's root makes the rule to be applied globally.

GOOD
lib/components/Item/index.js lib/components/Item/style.css
import style from './style.css'

const Item = ({ title, thumbnail }) =>
  <div className={style.container}>
    <img src={thumbnail} alt={title} />
  </div>

export default Item
.container > img {
  background-color: #CCCCCC;
}
BAD
lib/components/Item/index.js lib/components/Item/style.css
import style from './style.css'

const Item = ({ title, thumbnail }) =>
  <div className={style.container}>
    <img src={thumbnail} alt={title} />
  </div>

export default Item
img {
  background-color: #CCCCCC;
}

⬆️ Back to top

When using multiple selectors, give each selector its own line

Organize one selector per line, even when placing all of them at the same line doesn't exceed 80 columns.

GOOD BAD
.container > img,
.container > div,
.container > section {
  background-color: #CCCCCC;
}
.container > img, .container > div, .container > section {
  background-color: #CCCCCC;
}

⬆️ Back to top

Break lines in CSS function arguments

Sometimes, not to exceed the 80 columns limit, you need to break lines. While at it, be sure to do it right after the colon, and keep at one argument per line.

GOOD BAD
.container {
  background-color:
    linear-gradient(
      0deg,
      var(--color-light-yellow-12),
      var(--color-light-yellow-10),
    );
}
.container {
  background-color: linear-gradient(0deg, --color-light...
}

.container {
  background-color: linear-gradient(
    0deg, var(--color-light-yellow-12), var(--color-lig...
}

⬆️ Back to top

When writing rules, be sure to

  • Put a space before the opening brace {
  • In properties put a space after (but not before) the : character
  • Put closing braces } of rule declarations on a new line
  • Leave ONE blank line in between rule declarations
GOOD BAD
.container {
  font-size: 12pt;
}

.thumbnail {
  width: 160px;
  height: 90px;
}
.container{
  font-size:12pt;}
.thumbnail{
  width:160px;
  height:90px;}

⬆️ Back to top

CSS Design Patterns

The parent constrains the child

Leaf components shouldn't constrain width or height (unless it makes sense). That said, most components should default to fill the parent:

GOOD
lib/components/Input/index.js lib/components/Input/style.css
import style from './style.css'

const Input = ({ children }) =>
  <input className={style.input}>
    {children}
  </input>

export default Input
.input {
  box-sizing: border-box;
  padding: 10px;
  width: 100%;
}

⬆️ Back to top

The parent doesn't assume the child's structure

Sometimes we don't want to fill the whole width by default. An example is the button component, which we want to resize itself based on title width.

In this cases, we should allow the parent component to inject styles into the child component's container. The child is responsible for choosing where parent styles are injected.

For merging styles, always use classnames package. The rightmost arguments overrides the leftmost ones.

GOOD
lib/components/Button/index.js lib/components/Button/style.css
import classNames from 'classnames'
import style from './style.css'

const Button = ({ children, className }) =>
  <button className={classNames(style.button, className)}>
    {children}
  </button>

export default Button
.button {
  box-sizing: border-box;
  padding: 10px;
  width: 100%;
}

⬆️ Back to top

Components never leak margin

All components are self-contained and their final size should never suffer margin leakage! This allows the components to be much more reusable!

BAD GOOD
|--|-content size-|--| margin
 ____________________
|   ______________   | | margin
|  |              |  |
|  |              |  |
|  |              |  |
|  |______________|  |
|____________________| | margin

|---container size---|

   |-content size-|
    ______________
   |              |
   |              |
   |              |
   |______________|



⬆️ Back to top

The parent spaces the children

When building lists or grids:

  • Build list/grid items as separate components
  • Use the the list/grid container to space children
  • To space them horizontally, use margin-left
  • To space them vertically, use margin-top
  • Select the first-child to reset margins
GOOD
lib/containers/Reviews/index.js lib/containers/Reviews/style.css
import style from './style.css'

const Reviews = ({ items }) =>
  <div className={style.container}>
    {items.map(item =>
      <img src={item.image} alt={item.title} />
    )}
  </div>

export default Reviews
.container > img {
  margin-left: 10px;
}

.container > img:first-child {
  margin-left: unset;
}

⬆️ Back to top

Nested classes aren't for providing scope

CSS modules already provides us scope. We don't need to use nested classes for providing scope isolation. Use nested class selectors for modifying children based on parent class. A use case is when a component is in error or success state:

BAD
lib/components/Button/index.js lib/components/Button/style.css
import style from './style.css'

const Button = ({ children }) =>
  <button className={style.button}>
    <img className={style.icon} />
    {children}
  </button>

export default Button
.button {
  box-sizing: border-box;
  padding: 10px;
  width: 100%;
}

.button .icon {
  width: 22px;
  height: 22px;
}
GOOD
lib/components/Input/index.js lib/components/Input/style.css
import style from './style.css'

const Input = ({ value, onChange, error }) =>
  <div className={classNames({ [style.error]: error })}>
    <input onChange={onChange} />
    <p>{error}</p>
  </div>

export default Input
.error p {
  color: red;
  display: unset;
}

⬆️ Back to top

Variables, lots of variables!

We encourage the "variabilification". Always define variables to increase reuse and make styles more consistent. The CSS4 specification defines a way to declare native variables. We adopted them as the standard.

To define a variable accessible globally:

GOOD
app/App/variables.css app/components/Button/styles.css
:root {
  --color-green-1: #6CCFAE;
  --color-green-2: #6B66B5;
  --color-green-3: #AAC257;
  --color-green-4: #68B5C1;
}
.container {
  background-color:
    linear-gradient(
      0deg,
      var(--color-green-1),
      var(--color-green-2)
    );
}

⬆️ Back to top


More Repositories

1

superbowleto

🏈 A microservice to issue, register and manage boletos
JavaScript
595
star
2

cafe-com-testes

O Café com Testes é uma iniciativa interna da Pagar.me para compartilhar conhecimento sobre testes e boas práticas de desenvolvimento. Essa iniciativa foi inspirada no Testing on the Toilet do Google
479
star
3

pagarme-php

💙 Pagar.me's PHP API
PHP
343
star
4

lambda

🔮 Estudos obscuros de programação funcional
JavaScript
318
star
5

vagas

🤝 Venha fazer parte do nosso time
307
star
6

node-boleto

Boleto generator in Node.js
JavaScript
298
star
7

react-event-components

🛰 A set of React components designed to handle global events (interval, keyboard, touch, mouse, etc)
JavaScript
274
star
8

teleport

🍆 Trigger-based Postgres replicator in Go that works without superuser permissions
Go
233
star
9

git-style-guide

Git styleguide followed by us here at Pagar.me
135
star
10

tldr

📜 A microservice to store and display sales receipts
JavaScript
133
star
11

react-scripts-former-kit-dashboard

📊 A custom react-scripts for building highly-customizable dashboards using former-kit components
JavaScript
130
star
12

react-payment-card-component

💳 A modern credit card component for React
JavaScript
99
star
13

the-office

Escritório virtual da Pagar.me
Svelte
94
star
14

pagarme-ruby

Pagar.me's Ruby API
Ruby
80
star
15

pagarme-python

🐍 Pagar.me's Python library
Python
76
star
16

former-kit

✈️ Primitive and unstyled React components ready for receiving your own visual identity.
JavaScript
71
star
17

javascript-style-guide

🎨 Javascript styleguide followed by us here at Pagar.me
JavaScript
50
star
18

deployer

📟 A tool for fetching, building, pushing and deploying applications.
Go
47
star
19

pagarme-magento

🛒 Pagar.me's Magento plugin
PHP
46
star
20

pagarme-java

Pagar.me's Java API
Java
44
star
21

pagarme-net

Pagar.me .NET library
C#
41
star
22

artis

💳 Projeto de Checkout desenvolvido em parceria entre MundiPagg e Pagar.me.
JavaScript
40
star
23

escriba

📜 Logging on steroids
JavaScript
38
star
24

talks

🎬 Recursos e material de estudo para criar boas talks
38
star
25

business-calendar

Holiday and financial operation calendar database
CSS
31
star
26

former-kit-skin-pagarme

✈️ A skin for former-kit based on Pagar.me's brand.
CSS
25
star
27

pagarme-core-api-php

PHP
23
star
28

robrowser

🤖 Automated frontend tests in different browser stacks
JavaScript
22
star
29

pagarme-opencart

Modulo Pagar.me para OpenCart
PHP
22
star
30

edipsy

Decent EDI file parsing in Node.js
JavaScript
22
star
31

sqs-quooler

A complete queue consumer for SQS
JavaScript
21
star
32

mr-krabs

🦀 💰 A package to clear Fargate cluster tasks https://www.npmjs.com/package/mr-krabs
JavaScript
20
star
33

satan-pm

node cluster process manager, upstart friendly
JavaScript
18
star
34

biblioteca-virtual

Repositório com links para artigos, vídeos, cursos levantados pelos times
18
star
35

pagarme-nodejs-sdk

TypeScript
17
star
36

caesar-challenge

17
star
37

magento2

Magento2 Module for Pagar.me 2.0
PHP
16
star
38

pagarme-ng-checkout

Angular service to provide checkout functionality to your Angularjs application.
JavaScript
16
star
39

pagarme-pocs

Um repositório para armazenarmos todas as pocs e exemplos de códigos que fazemos.
JavaScript
15
star
40

opensource

This is a guide for sharing best practices in furtherance of our open source projects
15
star
41

pagarme-ios

Pagar.me's iOS API
Objective-C
15
star
42

cryptokit

Golang crypto wrapper with pluggable providers
Go
15
star
43

node-rsa-keygen

Native RSA keypair generator for Node
C++
14
star
44

emblematic-icons

Pagar.me's iconography
JavaScript
14
star
45

hermes

Angular.js $http wrapper for RESTful applications
JavaScript
14
star
46

cards-style-sheet

💳 A sheet of cards in CSS
CSS
14
star
47

pagarme-php-sdk

PHP
13
star
48

bifrost

🌈 Bifrost: Pagarme's bridge between browser and MPOS
C#
13
star
49

business-moment

Helpers for dealing with business days. Uses business-calendar as source.
JavaScript
13
star
50

pagarme-ng-dropdown

Pagar.me directive to provide a simple and quick dropdown from a provided array of options
JavaScript
13
star
51

p4g4rm3

Validador de senha de nossos serviços! ⛔
JavaScript
13
star
52

mpos-net-sdk

Pagar.me's mPOS SDK
C#
13
star
53

woocommerce

Woocommerce module for Pagar.me
PHP
12
star
54

papeis

Os papéis que temos no Pagar.me
11
star
55

pagarme-core-api-nodejs

JavaScript
10
star
56

dojo

Repositório para as práticas de Dojo do time de Tecnologia da Pagar.me
JavaScript
10
star
57

pagarme-ng-range

Pagar.me directive to provide a custom range element
JavaScript
9
star
58

pagarme-express-exemplo

Esse projeto é um guia do fluxo de uso das funções mais utilizadas da API do Pagar.me
JavaScript
9
star
59

pagarme-sass-styleguide

The awesome angular.js styleguide that we follow at Pagar.me
8
star
60

warp-pipe

Golang tools to handle postgres logical replication slots
Go
8
star
61

dust

⚙️ 🏜️ Grupo de estudos da linguagem Rust 🏜️ ⚙️
Rust
8
star
62

pagarme-core-api-python

Python
8
star
63

pagarme-angular-styleguide

The awesome angular.js styleguide that we follow at Pagar.me
8
star
64

pagarme-core-api-java

Java
8
star
65

pagarme-ng-tooltip

Pagar.me directive to provide simple a tooltip
JavaScript
8
star
66

pagarme-python-sdk

Python
7
star
67

deplorator

extreme secure deploy manager
JavaScript
7
star
68

brand

Pagar.me logos in optimized SVG
7
star
69

terraform-ecs-application

ECS + CODEDEPLOY integrated with canary capabilities
HCL
6
star
70

pagarme-core-api-dotnet-framework

C#
6
star
71

pagarme-developers

Pagar.me's Developer Blog
CSS
6
star
72

pinpadRNExample

Example para integração com Pinpad em React Native
JavaScript
6
star
73

livepatch

Patch JSON streams on the fly
JavaScript
6
star
74

css

✨ Estudos sobre toda a magia do CSS
5
star
75

monkeyflash

Awesome library for animation and web page automation
JavaScript
5
star
76

react-material-design-icon-components

React components for all material design icons.
JavaScript
5
star
77

bundler

Node.js private package manager
JavaScript
5
star
78

pagarme-net-standard-sdk

C#
5
star
79

pagarme-core-api-go

Go
5
star
80

pagarme-golang-sdk

Go
4
star
81

mpos-android

Exemplo de aplicação do SDK Android MPOS Pagar.me
Java
4
star
82

ecommerce-module-core

PHP Module Core for our modules
PHP
4
star
83

cluster-requiem

Enhacements for the cluster module in order to handle graceful shutdowns with jobs that aren't associated with a socket.
JavaScript
4
star
84

bluebird-ff

Bluebird functional/flow extensions
JavaScript
4
star
85

scripts-to-rule-them-all

Pagar.me's scripts to rule them all, Docker version
Shell
4
star
86

tabajara-replicator

MySQL to PostgreSQL replicator
Ruby
4
star
87

cadu-js

💚 CADU Javascript API
JavaScript
4
star
88

aws-challenges

Desafios para candidados a vagas do time infraestrutura AWS
4
star
89

pagarme-java-sdk

Java
4
star
90

arcaneshield

Python
4
star
91

ecs-task-def-replacements

JavaScript
4
star
92

pagarme-prestashop

Pagar.me - Prestashop Module
Smarty
4
star
93

barcode-backup

Please, do not use this repository for production it is for reference only! Thank you!
JavaScript
3
star
94

gulp-ngspec

Hard file management for gulp projects
JavaScript
3
star
95

elasticrecord

ElasticSearch trait for ORMs, batteries included.
JavaScript
3
star
96

post-mortem-reports

Outage post mortem reports
3
star
97

pagarme-core-api-dotnet-standard

C#
3
star
98

lambda-simple-deploy

💿 Package and update your existent AWS Lambda functions
JavaScript
3
star
99

moment

Moment proxy usando a TZ de America/Sao_Paulo
JavaScript
3
star
100

saphire

Ruby inspired type system for JavaScript
JavaScript
2
star