Portuguese (Português) translation by Erick Patrick (you can also view the original English article)

JSX parece uma mistura de XML e HTML. Usamos JSX com React para facilmente criar componentes para nossos apps. JSX vira JavaScript quando o React compila o código.
A beleza de React é que podemos criar código reutilizável e estruturar facilmente nossa app com componentes em mente. Por fim, a distância entre mock up/wireframe e implementação nunca esteve tão curta.
Nossa Primeira Experiência com JSX
Eis um exemplo de JSX usado para renderizar um HTML:
var div = <div className="foo" />; ReactDOM.render(div, document.getElementById('example'));
Para criar um componentes, basta usar uma variável local que inicia com uma letra maiúscula, por exemplo:
var MyComponent = React.createClass({/*...*/}); var myElement = <MyComponent someProperty={true} />; ReactDOM.render(myElement, document.getElementById('example'));
Nota: Temos diversas palavras reservadas no JSX, é JavaScript no final das contas—assim, as palavras chave class
e for
são desencorajada como nomes de atributos. Os componentes React esperam que esses nomes sejam className
e htmlFor
, por exemplo.
Aninhando Tags
Especifiquemos filhos dentro de nosso JSX, assim:
var User, Profile; // You write in JSX: var app = <User className="vip-user"><Profile>click </Profile></User>; // What will get outputted in JS: var app = React.createElement( User, {className:"vip-user"}, React.createElement(Profile, null, "click") );
Testando JSX
Usando Babel REPL para testar nosso JSX:
Sub-Componentes e Espaços de Nome
Criação de formulários é fácil com JSX e sub-componentes, por exemplo:
var Form = FormComponent; var App = ( <Form> <Form.Row> <Form.Label htmlFor='login' /> <Form.Input name='login' type='text' /> </Form.Row> <Form.Row> <Form.Label htmlFor='password' /> <Form.Input name='pass' type='password' /> </Form.Row> </Form> );
Para fazer isso funcionar, precisamos criar os sub-componentes como atributos do componente principal:
var FormComponent = React.createClass({ ... }); FormComponent.Row = React.createClass({ ... }); FormComponent.Label = React.createClass({ ... }); FormComponent.Input = React.createClass({ ... });
Expressões
Para usar JavaScript para criar algo a ser usado em algum atributo, React apenas precisa envolvê-lo em chaves {}
, assim:
// You write in JSX: var myUser = <User username={window.signedIn ? window.username : ''} />; // Will become this in JS: var myUser = React.createElement( User, {username: window.signedIn ? window.username : ''} );
Podemos apenas passar um booleano para atributos de formulário, como disabled
, checked
e outros. Esse valores também podem ser fixos se preferimos criá-los em HTML puro.
// Make field required <input type="text" name="username" required />; <input type="text" name="username" required={true} />; // Check by default <input type="checkbox" name="rememberMe" value="true" checked={true} />; // Enable a field <input type="text" name="captcha" disabled={false} />
Atributos de Ampliação
Quando quisermos configurar vários atributos, é melhor fazê-lo durante a declaração do componente, nunca depois. Fazê-lo depois é um anti-padrão perigoso que significa que podemos não ter esse dado até muito mais tarde na execução.
Adicionemos múltiplas propriedades ao componente dessa forma, usando o novo operador de ampliação (spread) ...
.
var props = {}; props.username = username; props.email = email; var userLogin = <userLogin {...props} />; ``` You can use these prop variables multiple times. If you need to override one of the properties, it can be done by appending it to the component after the `...` spread operator, for example: ```js var props = { username: 'jimmyRiddle' }; var userLogin = <userLogin {...props} username={'mickeyFinn'} />; console.log(component.props.username); // 'mickeyFinn'
Comentários em JSX
Podemos usar //
e /*...*/
dentro de nosso JSX. Por exemplo:
var components = ( <Navigation> {/* child comment, put {} around */} <User /* multi line comment here */ name={window.isLoggedIn ? window.name : ''} // Here is a end of line comment /> </Navigation> );
Armadilhas Comuns em JSX
Existem algumas coisas que podem confundir algumas pessoas no JSX, como quando adicionamos atributos a elementos HTML nativos que não existem na especificação HTML.
React não renderizará qualquer atributo em elementos HTML nativos que não esteja na especificação a não ser os data-*
:
<div data-custom-attribute="bar" />
Além disso, renderizar HTML com conteúdo dinâmico pode ser bem confunso pelo escapamento e proteção XSS que o React tem embutido. Por isso, o React provê dangerouslySetInnerHtml
.
<div dangerouslySetInnerHTML={{__html: 'Top level » Child'}} />
Exemplo de Aplicação de Chat
Talvez conheçam o app Gitter. É uma aplicação web de chat em tempo real focada em desenvolvedores. Muitas pessoas a usam para discutir seus projetos no GitHub, dada a fácil integração com GitHub e pela possibilidade de criação de canal para nossos repositórios.
Esse tipo de aplicação pode, facilmente, ser criada em React, implementando a API WebRTC
para criar um chat p2p no navegador. Para isso usaremos os módulos PeerJS
e socket.io
do Node.
Para dar uma idei da arquitetura da aplicação, eis um diagrama UML de baixo nível e básico:

ChatServer recebe mensagem sinal com PeerJS e cada cliente a usa como um procurador para cuidar da travessia do NAT.
Começaremos o app do zero para dar uma boa ideia de como criar uma aplicação React. Primeiro, criemos um novo diretório para a aplicação e o arquivo package.json
dentro.
{ "name": "react-webrtc-chat", "version": "0.0.0", "description": "React WebRTC chat with Socket.io, BootStrap and PeerJS", "main": "app.js", "scripts": { "start-app": "node app.js", "start": "npm run start-app" }, "keywords": [ "webrtc", "react" ], "license": "MIT", "dependencies": { "express": "~4.13.3", "peer": "~0.2.8", "react": "~0.12.2", "react-dom": "^0.14.1", "socket.io": "~1.0.6" }, "devDependencies": { "babel-preset-react": "^6.0.14", "babelify": "^7.1.0", "browserify": "^12.0.1" } }
Esse arquivo será usado pelo npm
para configurar facilmente a aplicação. Especificaremos nossas dependências: express
, uma framework web que servirá nosso app; peer
, o servidor peerjs que usaremos para sinalização; socket.io
, que usaremos para agrupamento e a implementação webRTC. react-bootstrap
e bootstrap
são pacotes para usar o framework CSS do Twitter para estilizar o app.
Precisaremos de alguns pacotes adicionais e para isso usaremos bower
.
Criemos bower.json
e adicionemos o seguinte:
{ "name": "react-webrtc-chat", "main": "app.js", "version": "0.0.0", "ignore": [ "**/.*", "node_modules", "bower_components", "public/lib", "test", "tests" ], "dependencies": { "react": "~0.12.2", "jquery": "~2.1.4", "eventEmitter": "~4.2.7", "peerjs": "~0.3.14", "bootstrap": "~3.3.5" } }
Com essa configuração, traremos react
, jQuery
, bootstrap
, eventEmitter
para lançar eventos e e a versão cliente de peerJS
para envolver a API da WebRTC.
Configuremos .bowerrc
, especificando onde instalar as coisas:
{ "directory": "src/lib" }
Daqui, apenas esperemos as dependências insralarem com:
$ bower install && npm install
Uma vez terminado, veremos os diretórios node_modules
e src/lib
. Eles contem os módulos prontos para uso.
Agora, criemos app.js
na pasta principal, junto do arquivo package.json
. Essa será a porta de entrada da aplicação.
//Configure our Services var express = require('express'), PeerServer = require('peer').PeerServer, events = require('./src/Events.js'), app = express(), port = process.env.PORT || 3001; //Tell express to use the 'src' directory app.use(express.static(__dirname + '/src')); //Configure the http server and PeerJS Server var expressServer = app.listen(port); var io = require('socket.io').listen(expressServer); var peer = new PeerServer({ port: 9000, path: '/chat' }); //Print some console output console.log('#### -- Server Running -- ####'); console.log('Listening on port', port); peer.on('connection', function (id) { io.emit(events.CONNECT, id); console.log('# Connected', id); }); peer.on('disconnect', function (id) { io.emit(events.DISCONNECT, id); console.log('# Disconnected', id); });
Isso criará um servidor Express, tornando os arquivos em src/
obtidos com bower
, acessíveis via HTTP. Então, uma instância de socket.io
será criada para observar o objeto expressServer
. Isso será usado para agrupar e facilitar o próximo passo para PeerServer
, que fará a parte real do WebRTC.
Para configurar um PeerServer
, precisamos especificar a porta
e o caminho
que o servidor executará e então configurar os eventos com o método .on
. Usaremos um arquivo separado, Events.js
, para especificar os eventos do app.
peer.on('connection', function (id) { io.emit(events.CONNECT, id); console.log('# Connected', id); });
Aqui usamos o evento events.CONNECT
para especificar quando uma usuário se conectou ao app. Isso será usado pelos estados dos componentes da visão para atualizar em tempo real.
Para isso, precisamos criar um servidor para as conexões peer-to-peer onde as procuraremos.
Criemos um arquivo src/Serve.js
e adicionemos o seguinte:
/* global EventEmitter, events, io, Peer */ 'use strict'; function ChatServer() { EventEmitter.call(this); this._peers = {}; } ChatServer.prototype = Object.create(EventEmitter.prototype); ChatServer.prototype.onMessage = function (cb) { this.addListener(events.MSG, cb); }; ChatServer.prototype.getUsername = function () { return this._username; }; ChatServer.prototype.setUsername = function (username) { this._username = username; }; ChatServer.prototype.onUserConnected = function (cb) { this.addListener(events.CONNECT, cb); }; ChatServer.prototype.onUserDisconnected = function (cb) { this.addListener(events.DISCONNECT, cb); }; ChatServer.prototype.send = function (user, message) { this._peers[user].send(message); }; ChatServer.prototype.broadcast = function (msg) { for (var peer in this._peers) { this.send(peer, msg); } }; ChatServer.prototype.connect = function (username) { var self = this; this.setUsername(username); this.socket = io(); this.socket.on('connect', function () { self.socket.on(events.CONNECT, function (userId) { if (userId === self.getUsername()) { return; } self._connectTo(userId); self.emit(events.CONNECT, userId); console.log('User connected', userId); }); self.socket.on(events.DISCONNECT, function (userId) { if (userId === self.getUsername()) { return; } self._disconnectFrom(userId); self.emit(events.DISCONNECT, userId); console.log('User disconnected', userId); }); }); console.log('Connecting with username', username); this.peer = new Peer(username, { host: location.hostname, port: 9000, path: '/chat' }); this.peer.on('open', function (userId) { self.setUsername(userId); }); this.peer.on('connection', function (conn) { self._registerPeer(conn.peer, conn); self.emit(events.CONNECT, conn.peer); }); }; ChatServer.prototype._connectTo = function (username) { var conn = this.peer.connect(username); conn.on('open', function () { this._registerPeer(username, conn); }.bind(this)); }; ChatServer.prototype._registerPeer = function (username, conn) { console.log('Registering', username); this._peers[username] = conn; conn.on('data', function (msg) { console.log('Message received', msg); this.emit(events.MSG, { content: msg, author: username }); }.bind(this)); }; ChatServer.prototype._disconnectFrom = function (username) { delete this._peers[username]; };
Isso é o cérebro da aplicação. Aqui configuramos o objeto ChatServer
com todas as funções.
Primeiro usamos socket.io
para estabelecer um sinal de um novo usuário conectado via events.CONNECT
:
ChatServer.prototype.connect = function (username) { var self = this; this.setUsername(username); this.socket = io(); this.socket.on('connect', function () { self.socket.on(events.CONNECT, function (userId) { if (userId === self.getUsername()) { return; } self._connectTo(userId); self.emit(events.CONNECT, userId); console.log('User connected', userId); });
Então, para conectar ao PeerServer, usamos o seguinte:
this.peer = new Peer(username, { host: location.hostname, port: 9000, path: '/chat' });
Entäao observamos por eventos através do método on
:
this.peer.on('open', function (userId) { self.setUsername(userId); }); this.peer.on('connection', function (conn) { self._registerPeer(conn.peer, conn); self.emit(events.CONNECT, conn.peer); });
Também temos nosso JSX dentro de componentes na pasta components/chat
. Tomemos um tempo para olhar todos no repositório. Focaremos no componente ChatBox
por hora:
/** @jsx React.DOM */ 'use strict'; var ChatBox = React.createClass({ getInitialState: function () { return { users: [] }; }, componentDidMount: function () { this.chatProxy = this.props.chatProxy; this.chatProxy.connect(this.props.username); this.chatProxy.onMessage(this.addMessage.bind(this)); this.chatProxy.onUserConnected(this.userConnected.bind(this)); this.chatProxy.onUserDisconnected(this.userDisconnected.bind(this)); }, userConnected: function (user) { var users = this.state.users; users.push(user); this.setState({ users: users }); }, userDisconnected: function (user) { var users = this.state.users; users.splice(users.indexOf(user), 1); this.setState({ users: users }); }, messageHandler: function (message) { message = this.refs.messageInput.getDOMNode().value; this.addMessage({ content: message, author : this.chatProxy.getUsername() }); this.chatProxy.broadcast(message); }, addMessage: function (message) { if (message) { message.date = new Date(); this.refs.messagesList.addMessage(message); } }, render: function () { return ( <div className="chat-box" ref="root"> <div className="chat-header ui-widget-header">React p2p Web RTC Chat</div> <div className="chat-content-wrapper row"> <UsersList users={this.state.users} username={this.props.username} ref="usersList"></UsersList> <MessagesList ref="messagesList"></MessagesList> </div> <MessageInput ref="messageInput" messageHandler={this.messageHandler}> </MessageInput> </div> ); } });
Essa classe lança mão do ChatServer
criado anteriormente, utilizando-o como procurador do componente ChatBox
.
Os componentes e bibliotecas são, por fim, renderizados na página index.html
e servidos via node, com express.
Para iniciar o app, executemos npm start
e visitemos http://localhost:3001
para ver o chat.
Publicando no Heroku
Publicar nas núvens é bem fácil com Heroku. Criemos uma conta gratuita e então instalemos o conjunto de ferramentas heroku
no nosso sistema. Para mais informações sobre como configurar heroku
, vá em Heroku Dev Center.
Agora que heroku
está disponível, acessemos e criemos um novo projeto, assim:
$ git clone git@github.com:tomtom87/react-p2p-chat.git $ cd react-p2p-chat $ heroku create Creating sharp-rain-871... done, stack is cedar-14 http://sharp-rain-871.herokuapp.com/ | https://git.heroku.com/sharp-rain-871.git Git remote heroku added
Aqui, obteremos um nome aleatório do Heroku para a URL do app—no nosso exemplo é http://sharp-rain-871.herokuapp.com/
. Heroku também cria um repositório git para o app.
Agora, é tão simples quanto enviar o código para heroku:
$ git push heroku master
Quando o envio terminar, podemos iniciar o serviço web com o seguinte:
$ heroku ps:scale web=1
Agora, visitemos a URL fornecida ou, como atalho, usemos o comando open
:
$ heroku open
Conclusões
Aprendemos a criar componentes JSX e integrá-los ao React, com um examplo detalhado de uma aplicação de chat. Tome um tempo lendo o códgo e veja como React e o diretório components/chat
funcionam.
Combinado à publicação no Heroku
, podemos começar a hackear e criar nossos próprios apps React
na núvem!
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post