Introdução ao Desenvolvimento Front-end com React

React é uma bibloiteca JavaScript desenvolvida pelo Facebook e Instagram, focada na criação de interfaces gráficas de usuário.

Exemplo Básico: Hello World

Para começar, vamos criar um exemplo simples que exibe "Hello, World!". Este código demonstra a integração básica do React com HTML e o uso do JSX, uma extensão de sintaxe que se parece com HTML.


<html>
<head>
   <meta charset="UTF-8">
   <title>React Hello World</title>
   <script src="https://unpkg.com/react/umd/react.development.js"></script>
   <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
   <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
   <div id="appRoot"></div>
   <script type="text/babel">
       const GreetingElement = <h1>Olá, Mundo!</h1>;

       ReactDOM.render(
           GreetingElement,
           document.getElementById('appRoot')
       );
   </script>
</body>
</html>

O atributo type="text/babel" no script é crucial para que o navegador interprete o JSX. O JSX permite misturra sintaxe semelhante a HTML com JavaScript.

Iterando com Mapeamento

Podemos usar o método map do JavaScript para renderizar listas de elementos dinamicamente.

const items = ['Maçã', 'Banana', 'Laranja'];
const listElements = items.map((item, index) =>
   <li key={index}>{item}</li>
);

ReactDOM.render(
   <ul>{listElements}</ul>,
   document.getElementById('listContainer')
);

Cada elemento na lista deve ter uma chave única (key), que ajuda o React a identificar quais itens foram alterados, adicionados ou removidos.

Componentização

Componentes são blocos de construção reutilizáveis. Criamos componentes usando React.createClass (ou classes ES6 em abordagens mais modernas). O nome do componente deve começar com uma letra maiúscula.

const CustomButton = React.createClass({
   render: function() {
       return <button>Botão Personalizado: {this.props.label}</button>;
   }
});

ReactDOM.render(
   <CustomButton label="Clique Aqui"/>,
   document.getElementById('buttonContainer')
);

Props: Propriedades de Componentes

this.props permite que um componente receba dados de seu pai. As propriedades são passadas como atributos no JSX.

const StudentList = React.createClass({
   render: function() {
       return (
           <ol>
               {React.Children.map(this.props.children, (child, index) =>
                   <li key={index}>{child}</li>
               )}
           </ol>
       );
   }
});

ReactDOM.render(
   <StudentList>
       <span>Alice</span>
       <span>Bob</span>
   </StudentList>,
   document.getElementById('studentListContainer')
);

this.props.children refere-se ao conteúdo aninhado dentro de um componente.

PropTypes: Validação de Props

propTypes é usado para definir os tipos esperados das props de um componente e se elas são obrigatórias. Isso ajuda na depuração e na garantia da integridade dos dados.

const UserProfile = React.createClass({
   getDefaultProps: function() {
       // Define valores padrão para as props
       return {
           userName: "Usuário Padrão"
       };
   },
   propTypes: {
       userName: React.PropTypes.string.isRequired // userName é uma string e é obrigatório
   },
   render: function() {
       return <h1>Perfil de: {this.props.userName}</h1>;
   }
});

const userNameValue = "React Developer";
ReactDOM.render(
   <UserProfile userName={userNameValue} />,
   document.getElementById('profileContainer')
);

DOM Virtual

O DOM Virtual é uma representação em memória do DOM real. O React usa o DOM Virtual para otimizar as atualizações, comparando a versão anterior com a nova e aplciando apenas as mudanças necessárias ao DOM real. Isso resulta em melhor performance.

const InputFocusComponent = React.createClass({
   focusInput: function() {
       // Acessa o elemento de input diretamente usando 'ref'
       const textInput = this.refs.myTextInput;
       alert('Valor atual: ' + textInput.value);
       textInput.focus();
   },
   render: function() {
       return (
           <div>
               <input type="text" ref="myTextInput" />
               <button onClick={this.focusInput}>Focar no Campo</button>
           </div>
       );
   }
});

ReactDOM.render(
   <InputFocusComponent />,
   document.getElementById('inputFocusContainer')
);

refs é um mecanismo para acessar nós do DOM ou instâncias de componentes.

Estado do Componente (State)

this.state armazena dados que podem mudar ao longo do tempo e afetam a renderização do componente. Mudanças no estado disparam uma nova renderização.

const ToggleButton = React.createClass({
   getInitialState: function() {
       return { isActive: false };
   },
   handleToggle: function() {
       // Use this.setState para atualizar o estado
       this.setState({ isActive: !this.state.isActive });
   },
   render: function() {
       const statusText = this.state.isActive ? 'Ativo' : 'Inativo';
       return (
           <p onClick={this.handleToggle}>
               Status: {statusText}. Clique para alternar.
           </p>
       );
   }
});

ReactDOM.render(
   <ToggleButton />,
   document.getElementById('toggleButtonContainer')
);

Formulários Controlados

Em React, formulários geralmente são "controlados", o que significa que o estado do componente React gerencia o valor do input.

const SimpleForm = React.createClass({
   getInitialState: function() {
       return { inputValue: 'Valor inicial' };
   },
   handleInputChange: function(event) {
       this.setState({ inputValue: event.target.value });
   },
   render: function() {
       return (
           <div>
               <input
                   type="text"
                   value={this.state.inputValue}
                   onChange={this.handleInputChange}
               />
               <p>Valor digitado: {this.state.inputValue}</p>
           </div>
       );
   }
});

ReactDOM.render(
   <SimpleForm />,
   document.getElementById('formContainer')
);

Ciclo de Vida do Componente

Componentes React passam por diferentes fases: montagem (inserção no DOM), atualização (re-renderização) e desmontagem (remoção do DOM). Cada fase tem métodos que podem ser "ganchos" (hooks) para executar código em momentos específicos.

  • Montagem: componentWillMount, componentDidMount
  • Atualização: componentWillUpdate, componentDidUpdate
  • Desmontagem: componentWillUnmount
const LifecycleLogger = React.createClass({
   componentWillMount: function() { console.log('O componente está prestes a ser montado.'); },
   componentDidMount: function() { console.log('O componente foi montado no DOM.'); },
   componentDidUpdate: function() { console.log('O componente foi atualizado.'); },
   componentWillUnmount: function() { console.log('O componente está prestes a ser desmontado.'); },
   render: function() { return <div>Componente com Logs do Ciclo de Vida</div>; }
});

const ControlLifecycle = React.createClass({
   mountComponent: function() {
       ReactDOM.render(<LifecycleLogger />, document.getElementById('lifecycleTarget'));
   },
   unmountComponent: function() {
       ReactDOM.unmountComponentAtNode(document.getElementById('lifecycleTarget'));
   },
   render: function() {
       return (
           <div>
               <button onClick={this.mountComponent}>Montar Componente</button>
               <button onClick={this.unmountComponent}>Desmontar Componente</button>
               <div id="lifecycleTarget"></div>
           </div>
       );
   }
});

ReactDOM.render(<ControlLifecycle />, document.getElementById('lifecycleControlContainer'));

Requisições AJAX

É comum buscar dados de APIs externas. O método componentDidMount é um local ideal para iniciar essas requisições. Após receber os dados, usamos this.setState para atualizar a interface.

// Supondo que jQuery esteja disponível para $.get
const GitHubGists = React.createClass({
   getInitialState: function() {
       return { username: '', lastGistUrl: '' };
   },
   componentDidMount: function() {
       const apiUrl = this.props.source;
       $.get(apiUrl, (result) => {
           if (this.isMounted()) { // Verifica se o componente ainda está montado
               const firstGist = result[0];
               this.setState({
                   username: firstGist.owner.login,
                   lastGistUrl: firstGist.html_url
               });
           }
       }).fail((jqXHR, textStatus, errorThrown) => {
           console.error("Erro ao buscar dados:", textStatus, errorThrown);
           if (this.isMounted()) {
               this.setState({ username: 'Erro', lastGistUrl: '#' });
           }
       });
   },
   render: function() {
       return (
           <div>
               Último gist de {this.state.username}:
               <a href={this.state.lastGistUrl} target="_blank">Link</a>
           </div>
       );
   }
});

ReactDOM.render(
   <GitHubGists source="https://api.github.com/users/octocat/gists" />,
   document.getElementById('gistContainer')
);

Trabalhando com Promises

Promises são uma forma moderna de lidar com operações assíncronas. Podemos passá-las como props para componentes que gerenciam seus estados (loading, success, error).

const GithubRepoList = React.createClass({
   getInitialState: function() {
       return { loading: true, error: null, repos: [] };
   },
   componentDidMount() {
       this.props.repoPromise
           .then(data => {
               this.setState({ loading: false, repos: data.items });
           })
           .catch(error => {
               this.setState({ loading: false, error: error.message });
           });
   },
   render: function() {
       if (this.state.loading) {
           return <span>Carregando repositórios...</span>;
       }
       if (this.state.error) {
           return <span>Erro: {this.state.error}</span>;
       }
       const repoItems = this.state.repos.map((repo, key) => (
           <li key={key}>
               <a href={repo.html_url}>{repo.name}</a> - {repo.description} ({repo.stargazers_count} estrelas)
           </li>
       ));
       return (
           <div>
               <h2>Repositórios Populares de JavaScript no GitHub</h2>
               <ul>{repoItems}</ul>
           </div>
       );
   }
});

// Exemplo de como chamar:
const searchUrl = 'https://api.github.com/search/repositories?q=javascript&sort=stars';
ReactDOM.render(
   <GithubRepoList repoPromise={$.getJSON(searchUrl)} />,
   document.getElementById('repoListContainer')
);

Tags: React javascript jsx componentes Ciclo de Vida

Publicado em 10-5 22:15