SlideShare une entreprise Scribd logo
1  sur  69
Télécharger pour lire hors ligne
EVOLUINDO A EXPERIÊNCIA WEB
NO SPORTV PLAY COM REACT
GUILHERME GARNIER
https://blog.guilhermegarnier.com
@gpgarnier
Estamos contratando!
https://talentos.globo.com
ARQUITETURA ORIGINAL
COMPONENTES
PROBLEMAS
Como padronizar?
Como compartilhar?
Como atualizar?
OPORTUNIDADE
resolver problemas com componentes
atualização
padronização
compartilhamento
rever a arquitetura
melhorar a experiência do usuário
COMPONENTES
// Modelo imperativo, c/ jQuery
$("button").prop("disabled", true)
 
$("textarea").on("input", function() {
if ($(this).val().length > 0) {
$("button").prop("disabled", false)
} else {
$("button").prop("disabled", true)
}
})
// Modelo declarativo, c/ React
class TweetBox extends Component {
state = { text: "" }
 
handleChange(event) {
this.setState({ text: event.target.value })
}
 
render() {
return (
<div>
<textarea onChange={this.handleChange}></textarea>
<button disabled={this.state.text.length === 0}>Tweet</button>
</div>
)
}
}
ARQUITETURA DAS APIS
PROBLEMAS
Muitas APIs internas
Muitas requisições
Acoplamento entre apps antigas e novas
BACK-END FOR FRONT-END
PATTERN
http://samnewman.io/patterns/architectural/bff/
http://philcalcado.com/2015/09/18/the_back_end_for_front_end_pattern
_bff.html
VANTAGENS
APIs específicas
Desacoplamento entre apps
Otimização (menos requisições, payload menor)
DESVANTAGENS
duplicação de código
duplicação de APIs
ACOPLAMENTO
GERENCIAMENTO DE ESTADO
dados do usuário
campanhas de trial
import { createStore } from 'redux'
 
// Create reducer
counter(state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
 
// Create store
let store = createStore(counter)
 
// React to store changes
store.subscribe(() =>
console.log(store.getState())
)
 
// Dispatch actions
store.dispatch({ type: 'INCREMENT' }) // 1
store.dispatch({ type: 'INCREMENT' }) // 2
store.dispatch({ type: 'DECREMENT' }) // 1
import {observable, autorun} from 'mobx'
 
const counter = observable(0)
 
autorun(() => console.log(counter.get()))
 
counter.set(counter.get() + 1) // 1
counter.set(counter.get() + 1) // 2
counter.set(counter.get() - 1) // 1
"Redux offers a tradeoff..."
"... if you’re just learning React, don’t make Redux
your first choice."
ARQUITETURA DO CSS
class HelloWorld extends Component {
render() {
const styles = {
margin: "10px",
color: "red"
}
return (
<div style={styles}>
Hello, world!
</div>
)
}
}
CSS INLINE?
CSS INLINE
PROBLEMAS
não permite reaproveitar estilos
não suporta pseudo classes (:hover, :last-child)
não suporta media queries
não permite aplicar estilo em cascata
ex: header img { border: "1px solid black" }
CSS INLINE
VANTAGENS
não precisa realizar um request extra para o CSS
isolamento
facilita manutenção (evita código não usado)
CSS IN JS
import disabledColor from "./constants"
 
class HelloWorld extends Component {
state = {
enabled: true
}
 
render() {
const styles = {
marginBottom: "5px",
color: this.state.enabled ? "red" : disabledColor
}
 
return (
<div style={styles}>
Hello, world!
</div>
)
}
}
class Alert extends Component {
getStyles() {
return {
alert: {
backgroundColor: "white",
":hover": { cursor: "pointer" },
"@media (min-width: 320px)": { fontSize: "15px" },
 
success: { backgroundColor: "green" },
error: { backgroundColor: "red" }
}
}
}
 
render() {
const styles = this.getStyles()
return (
<div style={[styles.alert, styles.alert[this.props.type]]}>
{ this.props.message }
</div>
)
}
}
RADIUM
PROBLEMAS
performance (pseudo classes e media queries resolvidos por JS)
não resolve problema de estilos em cascata ( header img { ... })
RADIUM
ALTERNATIVAS
CSS Modules
CSS puro!
https://github.com/Khan/aphrodite
ORGANIZAÇÃO DOS
COMPONENTES
RESPONSABILIDADES
consumir dados (via API ou props)
exibir dados
PRESENTATIONAL & CONTAINER
COMPONENTS
Separação de responsabilidades
https://medium.com/@dan_abramov/smart-and-dumb-components-
7ca2f9a7c7d0
CONTAINER COMPONENT
recebe dados via API ou props
formata dados
repassa os dados para descendentes (presentational ou container)
não tem conhecimento do markup
ENTRADA
SAÍDA
[{
"title": "SporTV 3",
"thumbUrl": "http://...",
"schedule": [
{
"startsAt": "2017-04-17T11:30:00-03:00",
"durationInMinutes": 120,
"title": "Masters 1000",
"description": "Monte Carlo",
"live": true
}, ...
]
}, ...]
[{
"title": "SporTV 3",
"description": "Masters 1000",
"subDescription": "Monte Carlo",
"thumbUrl": "http://...",
"live": true
}, ...]
PRESENTATIONAL COMPONENT
markup
estilo
interações (clicks, eventos)
VANTAGENS
componentes com menos responsabilidades
facilita os testes
facilita o compartilhamento
COMPARTILHAMENTO DE
COMPONENTES
BIBLIOTECA DE COMPONENTES DE VÍDEO
reaproveitar código
trocar conhecimento entre times
aproximar a experiência de uso dos
produtos de vídeo
PROBLEMAS
dependências dos componentes (ex: Radium)
forma de exportar componentes
transpilado ou não (ou ambos)
incluir dependências no bundle ou não
interface dos componentes
ownership (quem é responsável por corrigir um bug?)
OTIMIZAÇÕES
STATELESS COMPONENTS
https://hackernoon.com/react-stateless-functional-components-nine-
wins-you-might-have-overlooked-997b0d933dbc
const Footer = (props) => {
return (
<footer>
<p>© 2017 Globo Comunicação e Participações S.A.</p>
<a href={props.url}>Política de Privacidade</a>
</footer>
)
}
CACHEAR CALLBACKS
class VideoList extends Component {
thumbClick() {
metrics.register(`click video-list #{this.props.name}`)
}
 
render() {
<VideoThumb title="video 1" onClick={this.thumbClick.bind(this)}>
<VideoThumb title="video 2" onClick={this.thumbClick.bind(this)}>
}
}
CACHEAR CALLBACKS
const sum = (a, b) => a + b
 
const bind1 = sum.bind(this)
const bind2 = sum.bind(this)
 
bind1 == bind1 // true
bind1 == bind2 // false
CACHEAR CALLBACKS
class Home extends Component {
constructor() {
this.thumbClickCallback = this.thumbClick.bind(this)
}
 
thumbClick() {
metrics.register(`click video-list #{this.props.name}`)
}
 
render() {
<VideoThumb title="video 1" onClick={this.thumbClickCallback}>
<VideoThumb title="video 2" onClick={this.thumbClickCallback}>
}
}
CONCLUSÃO
facilitou a criação de componentes
maduro e evoluindo rapidamente
ecossistema crescente
gerenciamento de estado
MobX para aplicações menores
Redux para aplicações mais complexas
arquitetura do CSS em discussão
compartilhar componentes não é tão simples quanto parece
PERGUNTAS?
Slides:
https://blog.guilhermegarnier.com
@gpgarnier
https://blog.guilhermegarnier.com/sportv-play/

Contenu connexe

Similaire à Evoluindo a experiência web no SporTV Play com React

Similaire à Evoluindo a experiência web no SporTV Play com React (20)

Dinamizando Sites Estáticos
Dinamizando Sites EstáticosDinamizando Sites Estáticos
Dinamizando Sites Estáticos
 
Aplicações rápidas para a Web com Django
Aplicações rápidas para a Web com DjangoAplicações rápidas para a Web com Django
Aplicações rápidas para a Web com Django
 
Backbone.js - A espinha dorsal de aplicações web
Backbone.js - A espinha dorsal de aplicações webBackbone.js - A espinha dorsal de aplicações web
Backbone.js - A espinha dorsal de aplicações web
 
JavaScript Model-View no Frontend
JavaScript Model-View no FrontendJavaScript Model-View no Frontend
JavaScript Model-View no Frontend
 
Backbone.js + Rails - Front-end e back-end conectados
Backbone.js + Rails - Front-end e back-end conectadosBackbone.js + Rails - Front-end e back-end conectados
Backbone.js + Rails - Front-end e back-end conectados
 
Os 10 Maus Hábitos dos Desenvolvedores JSF
Os 10 Maus Hábitos dos Desenvolvedores JSFOs 10 Maus Hábitos dos Desenvolvedores JSF
Os 10 Maus Hábitos dos Desenvolvedores JSF
 
LambdaDay: Backbone.js
LambdaDay: Backbone.jsLambdaDay: Backbone.js
LambdaDay: Backbone.js
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017
 
Tutorial.yii
Tutorial.yiiTutorial.yii
Tutorial.yii
 
JavaScript e JQuery para Webdesigners
JavaScript e JQuery para WebdesignersJavaScript e JQuery para Webdesigners
JavaScript e JQuery para Webdesigners
 
Rapid Application Development com Tapestry 5
Rapid Application Development com Tapestry 5Rapid Application Development com Tapestry 5
Rapid Application Development com Tapestry 5
 
TDC2011 - Desenvolvimento de jogos com Javascript e HTML5
TDC2011 - Desenvolvimento de jogos com Javascript e HTML5TDC2011 - Desenvolvimento de jogos com Javascript e HTML5
TDC2011 - Desenvolvimento de jogos com Javascript e HTML5
 
don't repeat yourself front-ender
don't repeat yourself front-enderdon't repeat yourself front-ender
don't repeat yourself front-ender
 
Os 10 maus habitos dos desenvolvedores jsf (JustJava e CCT)
Os 10 maus habitos dos desenvolvedores jsf (JustJava e CCT)Os 10 maus habitos dos desenvolvedores jsf (JustJava e CCT)
Os 10 maus habitos dos desenvolvedores jsf (JustJava e CCT)
 
Hello vue
Hello vueHello vue
Hello vue
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOL
 
Introdução ao Titanium Mobile
Introdução ao Titanium MobileIntrodução ao Titanium Mobile
Introdução ao Titanium Mobile
 
Palestra - Iniciando no Jquery
Palestra - Iniciando no JqueryPalestra - Iniciando no Jquery
Palestra - Iniciando no Jquery
 
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
 
Desenvolvimento de aplicações para o Google App Engine
Desenvolvimento de aplicações para o Google App EngineDesenvolvimento de aplicações para o Google App Engine
Desenvolvimento de aplicações para o Google App Engine
 

Evoluindo a experiência web no SporTV Play com React