diessi.caBlog
March 21, 2016

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. ^[Sugiro a leitura de Functional Stateless Components in React 0.14]

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.