5 Bibliotecas Essenciais para Desenvolver React Apps

O conjunto de ferramentas, boilerplates e bibliotecas disponíveis formam um ecossistema incrível em torno do React.

No meio de tudo, existem ferramentas que são comuns – e essenciais – a diversas aplicações, independente de suas arquiteturas. Cito cinco delas.

1. classnames

Muitas vezes, no React, um estado representará um comportamento visual do componente (“selecionado”, “pressionado”, “focado”), normalmente associado a uma classe CSS.

Um botão e seus estados disabled e hovered, por exemplo, ficariam assim:

<button
  type="submit"
  onMouseOver={...}
  className={classNames('button', this.props.className, {
    'button--disabled': this.state.isDisabled,
    'button--hovered': this.state.isHovered
  })}
/>

Perceba que o Classnames facilita a manipulação condicional de classes com React, removendo vários blocos de if/else do seu código.

2. react-router

Se você está desenvolvendo uma Single-page Application, você precisará sincronizar a interface do usuário com a URL.

O React Router é a melhor solução de rotas para aplicações desenvolvidas com React, e isso se deve bastante a sua API declarativa e pensada para componentes.

Considere a seguinte configuração de rotas:

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, browserHistory } from 'react-router'

import App from 'components/App'
import Homepage from 'screens/Homepage'
import About from 'screens/About'
import Contact from 'screens/Contact'

render((
  <Router history={browserHistory}>
    <Route path="/" component={App}>
      <IndexRoute component={Homepage}/>
      <Route path="about" component={About}/>
      <Route path="contact" component={Contact} />
    </Route>
  </Router>
), document.getElementById('react-root'))

Perceba que há uma instância inicial da rota e outras rotas aninhadas, formando uma hierarquia. Essa hierarquia é a essência do React Router.

Considere que temos um App (App.js):

import React, { Component } from 'react'
import { IndexLink, Link } from 'react-router'

class App extends Component {
  render() {
    return (
      <div>
        <nav>
          <IndexLink to="/">Homepage</li>
          <Link to="/about">About</Link>
          <Link to="/contact">Contact</Link>
        </nav>

        <div>
          {this.props.children}
        </div>
      </div>
    )
  }
}

export default App

Dica: O componente acima não tem um estado próprio, portanto, ele é um Pure Component (ou Dumb Component). Componentes sob estas condições podem – e devem – ser transformados em Stateless Functional Components. [1]

Uma explicação rápida: Todas as subrotas da rota do componente App (os <Route> dentro de <Route>) terão seus componentes transferidos como props para o componente App (e por isso o this.props.children) ao entrar na rota através do <Link>.

A documentação do React Router dispensa quaisquer outras explicações!

3. react-helmet

Dificilmente você usará o React Router sem o Helmet. O Helmet te dá, no próprio componente, o controle do head do documento.

Um caso de uso simples é alterar o título do documento, útil quando a aplicação entra em uma nova rota:

<Helmet title="Carrinho de Compras" />

4. jsx-control-statements

JSX facilita a escrita da marcação do componente e torna seu código mais fácil de ler e entender. Mas e quando a renderização do componente é condicional? E quando renderizamos componentes dinamicamente?

Seu código termina provavelmente assim:

<div>
  {todos.map(function (todo, index) {
    return <TodoItem data={todo} key={index} />
  })}
</div>

E assim:

<div>
  {condition &&
    <span></span>
  }
</div>

Ou de uma das várias outras formas: condicionais inline, operações ternárias, funções para renderizar componentes condicionalmente… Práticas que, em grande escala, podem prejudicar a legibilidade do código. E é na legibilidade que o jsx-control-statements vence.

O primeiro exemplo, por exemplo, ficaria assim:

<div>
  <For each="todo" index="index" of={todos}>
    <TodoItem data={todo} key={index} />
  </For>
</div>

5. axios ou Fetch API

Não é uma dependência apenas de aplicações React, mas você provavelmente vai precisar de um cliente HTTP. (Um cliente HTTP de gente adulta, que não é o $.ajax.) Existem duas ótimas opções: axios e o fetch (“WHATWG Fetch API”).

axios

Uma biblioteca maravilhosa.

A API do axios é completa: têm interceptadores de requisição, múltiplas requisições em paralelo… E suas requisições retornam lindas promises.

Fazendo uma requisição POST:

import axios from 'axios'

axios.post(
  '/api/pets',
  { name: 'Bard', cat: false },
  { headers: {'X-Custom-Header': 'foobar'} }
)
  .then(() => console.log('Pet salvo com sucesso!'))
  .catch(response => console.log(response))

Fetch API

O fetch, por outro lado, já é um living standard, e, nesse momento, tem suporte básico nos navegadores Firefox, Chrome e Opera. É recomendado, no entanto, o uso de um polyfill, por ser uma tecnologia ainda experimental.

A mesma requisição POST ficaria assim:

fetch('/api/pets', {
  method: 'post',
  headers: { 'X-Custom-Header': 'foobar' },
  body: { name: 'Bard', cat: false }
})
  .then(() => console.log('Pet salvo com sucesso!'))
  .catch(response => console.log(response))

Você pode saber mais sobre o Fetch API no Mozilla Developer Network.


Considerações

Embora eu tenha citado apenas cinco, existem diversas bibliotecas e componentes que descomplicam o processo de desenvolvimento de uma aplicação com React. Sem dúvidas, é um dos ecossistemas mais relevantes que front-end já teve.

Destaco que não cobri um tópico que, quando se trata de React, é bastante pertinente: formulários. Lidar com formulários no React é complicado. Nesse primeiro momento, resolvi deixar o tema de lado para não fugir da proposta do artigo.


  1. Sugiro a leitura de Functional Stateless Components in React 0.14 ↩︎