React - Primeiros passos

April 12, 2017

Fala pessoal, tudo certo? Hoje, vou falar um pouquinho de React, a library para Front-end feita pelo Facebook e que tem ganhado muita popularidade nos últimos tempos. Bem, todo mundo já deve ter ouvido falar sobre, e nesse post eu vou falar um pouco sobre como o React funciona e como você pode dar os primeiros passos com ela para criar uma aplicação web.

Ao final do post, você pode encontrar o código final em um repositório no Github.

O que é o React

O Facebook, criador do React, define o mesmo como uma library Javascript para construção de interfaces de usuário, apresentando como principais características ser declarativa, baseada em componentes e seguindo o conceito de “Aprenda uma vez, escreva em qualquer lugar”. O React também utiliza JSX, uma linguagem com sintaxe semelhante à do HTML, mas com algumas particularidades que facilitam e muito a criação de interfaces e componentes. Avaliemos rapidamente estas três características principais do React.

Declarativa

Um conceito usualmente aceito para programação declarativa é o de que neste tipo de programação, você define o que você quer, enquanto que no estilo ao qual é normalmente comparado, o estilo imperativo, você enumera cada passo, indicando como conseguir aquilo que você quer. Da forma como o React funciona, é assim que você define sua interface, e veremos como mais a frente.

Baseada em Componentes

Crie componentes isolados, cada um contendo seus próprios métodos, estado e propriedades (states e props), e combine-os para criar interfaces complexas de usuário.

Aprenda Uma Vez, Escreva em Qualquer Lugar

O React não assume nada com relação à tecnologia que você usa. Você pode usar o React com Django, com Angular, com Rails, combinar com NodeJS. Além disso, também é possível criar aplicativos para celular utilizando o React Native.

Primeiros Passos

Chega de teoria e vamos aos primeiros passos. Começar a programar com React é muito fácil. Para começar, vamos criar uma estrutura básica: uma pasta public, com o arquivo index.html importando 3 libraries, que iremos precisar, que são o Babel, React e React DOM. Você pode referencia-los através do CDNJs, e seu arquivo inicial ficará da seguinte forma:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/6.1.19/browser.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
    </head>

    <body>
        <div id="app"></div>        
    </body>
</html>

Este div, com o id app, será o container para sua aplicação. É onde o React irá renderizar código em JSX, ou algum componente que criamos. Para renderizar nosso primeiro conteúdo com JSX, vamos usar a função render, do React DOM. Passaremos dois parâmetros para esta função. O primeiro é o código JSX que queremos renderizar, e o segundo é aonde esse código JSX será renderizado, que como já falamos, será o div com o id app. Para isso, vamos usar a função getElementById, do Javascript. Primeiramente, vamos renderizar um simples parágrafo:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
    </head>

    <body>
        <div id="app"></div>        

        <script type="text/babel">
            ReactDOM.render(
                First React App,
                document.getElementById('app')
            );
        </script>
    </body>    
</html>

Vamos usar o “http-server” (falei dele nesse post, clica aí e procura por http-server) para servir nossos arquivos. Rode o comando http-server e acesse http://localhost:8080/. Você verá o parágrafo na sua página. Parabéns, você criou sua primeira aplicação em React, funcionando.

Um pouquinho de JSX

O JSX tem mais algumas funcionalidades adicionais interessantes. A primeira delas é que você pode embutir código Javascript no layout do seu componente. Basta inserir o código Javascript entre chaves ({}). Vamos modificar nosso exemplo um pouquinho:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
    </head>

    <body>
        <div id="app"></div>        

        <script type="text/babel">
            var today = new Date();

            ReactDOM.render(
                Hello, 2 + 2 = {2 + 2}  and today is day {today.getDate()} of the month {today.getMonth() + 1},
                document.getElementById('app')
            );
        </script>
    </body>    
</html>

Embutimos um pouco de Javascript no meio do layout, e o que você deve ver ao acessar o seu localhost é algo semelhante com a imagem abaixo:

Image of web page built with React with a simple paragraph

Agora que já vimos como começar, vamos separar um pouco as coisas. Vamos tirar este script do final do nosso body e jogar em um arquivo separado. Este arquivo será o app.jsx, que ficará dentro da pasta public, na mesma pasta do seu arquivo index.html. Depois, vamos definir o atributo src do script que estava no index.html para app.jsx, para que ele possa fazer referência a este novo arquivo que criamos, com o código para renderizar o elemento p dentro do div. O arquivo index.html ficará assim:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
    </head>

    <body>
        <div id="app"></div>        

        <script type="text/babel" src="app.jsx"></script>
    </body>    
</html>

E o arquivo app.jsx ficará desta forma:

var today = new Date();

ReactDOM.render(
    Hello, 2 + 2 = {2 + 2}  and today is day {today.getDate()} of the month {today.getMonth() + 1},
    document.getElementById('app')
);

Pronto. Agora temos nosso HTML e nosso código Javascript separados em arquivos diferentes. Vamos criar nosso primeiro componente:

Nosso Primeiro Componente React

Para criar componentes, você usualmente verá pelos guias, sites e tutoriais, duas formas possíveis. Existem também uma forma mais simples, mas mais limitada, que é basicamente a criação de uma função recebe como argumento um objeto props com dados que você deseja passar ao componente e retorna um elemento JSX. Basicamente, algo como o código abaixo (aproveitando o exemplo da documentação oficial), que pode ser feito em nosso arquivo app.jsx:

var props = {name: 'Felipe'};

function HelloComponent(props) {
    return Hello, {props.name}
}

ReactDOM.render(
    HelloComponent(props),
    document.getElementById('app')
);

props é uma abreviação de properties, ou propriedades, que nada mais são do que dados a serem utilizados pelo componente para sua lógica e renderização, e são passados para o componente.

Esta forma que vimos acima não é muito utilizada, mas ainda consta na documentação do React. Entre as formas mais utilizadas, existem duas. A primeira, mais antiga, utiliza o método createClass() do React. Dentro dele, definimos o método render(), que indica aquilo que deve ser exibido quando este componente é renderizado. Este método deve ser usado se você ainda não utiliza as funcionalidades do ES6. Mas como nós temos o Babel, nós temos estas funcionalidades, e iremos usar a nova forma, que é a recomendada atualmente na documentação oficial do React. E para quem usa o ES6, a forma indicada para criar um componente é extendendo a class do ES6 React.Component. Depois, passamos para o método render este componente, com a sintaxe similar à de um elemento HTML. Repare a necessidade da / no final. Caso você a esqueça, o código não irá funcionar. Vejamos em nosso exemplo:

class HelloComponent extends React.Component {
    render() {
        return (
            This is HelloComponent            
        );
    }
}

ReactDOM.render(
    <HelloComponent/>,
    document.getElementById('app')
)

Para passar props para o componente, basta inclui-las como atributos, especificando seu valor dentro de chaves, na hora de passar o componente ao render, e recupera-las dentro do componente através do this.props mais o nome da propriedade. Vejamos no exemplo para que fique mais claro:

class HelloComponent extends React.Component {
    render() {
        var name = this.props.name;

        return (
            Hello, {name}. This is HelloComponent            
        );
    }
}

ReactDOM.render(
    <HelloComponent name={"Felipe"} />,
    document.getElementById('app')
)

Agora que falamos de componentes e props, vamos falar um pouquinho de state.

Componentes e state

Enquanto as props são valores passados ao componente, o state é o estado atual do componente. Valores e dados que definem como um componente se comporta e é renderizado. Segundo a documentação oficial, o state é semelhante às props, dados usados pelo componente, mas é totalmente controlado pelo próprio.

Para definir o state inicial, precisamos criar um construtor no componente, e dentro deste construtor, damos um valor para this.state, que será um objeto com toda a definição do state inicial do componente. Vamos adicionar um contador, com o nome counter, ao state e adicionar um parágrafo no render do nosso componente com o valor do contador, que recuperamos através do this.state.counter:

class HelloComponent extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            counter: 0
        }
    }

    render() {
        var name = this.props.name;
        var counter = this.state.counter;

        return (
            Hello, {name}. This is HelloComponent
            The current counter value is: {counter}
        );
    }
}

ReactDOM.render(
    <HelloComponent name={"Felipe"} />,
    document.getElementById('app')
)

Opa, temos um erro. Se você atualizar seu navegador e for até o console de Javascript do navegador (no Chrome, aperte F12 e clique em Console), poderá ver a seguinte mensagem de erro: “Uncaught SyntaxError: http://localhost:8080/app.jsx: Adjacent JSX elements must be wrapped in an enclosing tag (16:12)“. Como o próprio erro diz, o JSX requer que no return de qualquer elemento, sempre haja um elemento “pai”, que englobe todos os outros elementos. Um problema facilmente solucionado ao incluir um div que englobe os 2 parágrafos:

class HelloComponent extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            counter: 0
        }
    }

    render() {
        var name = this.props.name;
        var counter = this.state.counter;

        return (
            <div>
                Hello, {name}. This is HelloComponent
                The current counter value is: {counter}
            </div>
        );
    }
}

ReactDOM.render(
    <HelloComponent name={"Felipe"} />,
    document.getElementById('app')
)

Se mudamos a definição do counter, na linha 6, de 0 para outro valor, 3, por exemplo, esta mudança se reflete em nossa página. Vamos agora criar um botão dentro do nosso componente. Este botão, ao ser clicado, irá chamar uma função que irá atualizar nosso state, aumentando em 1 o valor do counter. Esta mudança será refletida imediatamente na página. Vamos lá:

class HelloComponent extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            counter: 0
        }
    }

    render() {
        var name = this.props.name;
        var counter = this.state.counter;

        return (
            <div>
                Hello, {name}. This is HelloComponent
                The current counter value is: {counter}
                <button>Increment</button>
            </div>
        );
    }
}

ReactDOM.render(
    <HelloComponent name={"Felipe"} />,
    document.getElementById('app')
)

Pronto, já temos nosso botão. Agora vamos criar nossa função e vamos atrelar a mesma ao botão que criamos, com o evento onClick. Vamos criar o método handleIncrement, que será o responsável por incrementar a propriedade counter do state, definindo como o valor do counter no state o valor atual do mesmo (this.state.counter) + 1. E por fim, temos que fazer o bind da função dentro do constructor, para que o this esteja disponível quando a chamarmos e a mesma possa acessar, por exemplo o método setState do componente, responsável por atualizar o state. Vamos lá:

class HelloComponent extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            counter: 0
        }

        this.handleIncrement = this.handleIncrement.bind(this);
    }

    handleIncrement() {
        this.setState({
            counter: this.state.counter + 1
        })
    }

    render() {
        var name = this.props.name;
        var counter = this.state.counter;

        return (
            <div>
                Hello, {name}. This is HelloComponent
                The current counter value is: {counter}
                <button onClick={this.handleIncrement} >Increment</button>
            </div>
        );
    }
}

ReactDOM.render(
    <HelloComponent name={"Felipe"} />,
    document.getElementById('app')
)

Agora, acesse a sua página novamente, clique no botão e veja a mágica acontecer. O contador aumenta em 1 a cada clique no botão. E assim, temos nosso componente, com props e state, além de um método que altera este valor contido no state do componente.

Resumo

Para resumir tudo o que fizemos neste post:

  • Criamos um arquivo HTML básico, referenciando o Babel, React e React DOM
  • Usamos o método “render” do React DOM para renderizar um parágrafo em nosso HTML com JSX, criando assim nossa primeira aplicação com React :)
  • Usamos mais um pouco de JSX para inserir código Javascript em nosso layout
  • Colocamos nossa estrutura HTML e nosso código Javascript em arquivos separados, facilitando a manutenção
  • Criamos nosso primeiro componente através da classe do Javascript ES6. Vimos o que são “props”, informação passada a um componente, e passamos uma “prop” para nosso componente
  • Aprendemos sobre “state”, que também são informações ou dados, mas totalmente gerenciados pelo componente em si, e não passados por outros componentes

Todo o código final encontrado neste post está neste repositório do Github: https://github.com/felipegalvao/react-first-steps

Abraços