You are on page 1of 12

Guía React

ES6 Training
let y const, nuevas formas de declarar variables
var a = 5;
var b = 10;

if (a === 5) {
let a = 4; // El alcance es dentro del bloque if
var b = 1; // El alcance es global

console.log(a); // 4
console.log(b); // 1
}
console.log(a); // 5
console.log(b); // 1
const c = 20;
c = 30;

Template strings
let text = 'Hola como estas';
let name = 'Harold';
console.log(text + ' ' + name);
console.log(`${text} ${name}`);

Arrow functions
Funciones anónimas
(params) => valorDeRetorno
function foo () {
console.log('normal function');
}
bar = () => console.log('arrow function');

function foo(a, b) {
return a+b;
}
bar = (a, b) => (a + b);

Métodos de programación funcional


let students = [{name: 'Harold', score: 10}, {name: 'Pedro', score: 8}, {name: 'Harold', score:
6}, {name: 'Harold', score: 4}];
Map
let studentsMap = students.map((s) => s.name);
Filter
let studentsFilter = students.filter((s) => s.score > 6);
Rest/Spread Operator
let prices = [100, 200, 300, 500];
let newPrices = [...prices];
let newPrices2 = ['A', ...prices, 'B'];

Práctica en REPL
Url: https://jscomplete.com/repl/
1er ejemplo, uso de REPL (​Read-Eval-Print-Loop​)
const Button = function () {
return (
<button>Go</button>
);
};

ReactDOM.render(<Button />, mountNode);

Recibe un único parámetro llamado props


const Button = function (props) {
return (
<button>{props.label}</button>
);
};

ReactDOM.render(<Button label="Do" />, mountNode);

Refactorizando a arrow function


const Button = (props) => (<button>{props.label}</button>);

Incrementando número
class Button extends React.Component {

constructor(props) {
super(props);
this.state = { counter: 0 };
}

render () {
return (
<button>{this.state.counter}</button>
)
}
}
ReactDOM.render(<Button />, mountNode);
Usando inicialización diferente y no en constructor (transform-class-properties babel
property)
handleClick = () => {
this.setState({
counter: this.state.counter + 1
});
};
Forma 1 solo Button
class Button extends React.Component {

state = { counter: 0 };

handleClick = () => {
this.setState((prevState) => ({
counter: prevState.counter + 1
}));
};

render () {
return (
<button onClick={this.handleClick}>
{this.state.counter}
</button>
)
}
}

ReactDOM.render(<Button />, mountNode);

Forma 2 Button + Result


class Button extends React.Component {

state = { counter: 0 };

handleClick = () => {
this.setState((prevState) => ({
counter: prevState.counter + 1
}));
};

render () {
return (
<button onClick={this.handleClick}>
+1
</button>
);
}
}

const Result = (props) => {


return (
<div>...</div>
);
};

class App extends React.Component {


render () {
return (
<div>
<Button />
<Result />
</div>
);
}
}

ReactDOM.render(<App />, mountNode);

Forma 3 Button + Result + App refactorizado, sin reutilización


class Button extends React.Component {
handleClick = () => { };

render () {
return (
<button onClick={this.props.onClickFunction}>
+1
</button>
);
}
}

const Result = (props) => {


return (
<div>{props.counter}</div>
);
};

class App extends React.Component {


state = { counter: 0 };

incrementCounter = () => {
this.setState((prevState) => ({
counter: prevState.counter + 1
}));
}

render () {
return (
<div>
<Button onClickFunction={this.incrementCounter} />
<Result counter={this.state.counter} />
</div>
);
}
}

ReactDOM.render(<App />, mountNode);

Versión final: Forma 4 Button + Result + App refactorizado, con reutilización


class Button extends React.Component {

handleClick = () => {
this.props.onClickFunction(this.props.incrementValue);
};

render () {
return (
<button onClick={this.handleClick}>
+{this.props.incrementValue}
</button>
)
}
}

const Result = (props) => {


return (
<div>{props.counter}</div>
);
};

class App extends React.Component {


state = { counter: 0 };

incrementCounter = (incrementValue) => {


this.setState((prevState) => ({
counter: prevState.counter + incrementValue
}));
}
render () {
return (
<div>
<Button incrementValue={1} onClickFunction={this.incrementCounter} />
<Button incrementValue={5} onClickFunction={this.incrementCounter} />
<Button incrementValue={10} onClickFunction={this.incrementCounter} />
<Button incrementValue={100} onClickFunction={this.incrementCounter} />
<Result counter={this.state.counter} />
</div>
);
}
}

ReactDOM.render(<App />, mountNode);

Ejemplo aplicación con integración API de Marvel


Url Marvel: ​https://developer.marvel.com/docs

Crear la app
create-react-app marvel-app

yarn add react-router-dom


yarn add crypto-js

index.html
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script
src="​https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js​"></script>

App.js

import React from 'react';


import { BrowserRouter as Router, Route } from "react-router-dom";

import HeroCardList from '../src/components/HeroCardList';


import Detail from '../src/components/Detail';

import './App.css';
const App = () => (
<Router>
<div>
<Route exact path="/" component={HeroCardList} />
<Route path="/:id" component={Detail} />
</div>
</Router>
);

export default App;

api/api.js

import md5 from "crypto-js/md5";

export const PUBLIC_KEY_MARVEL = "91bb24a91476c1b87d439fcaf4e8573a";


export const PRIVATE_KEY_MARVEL = "1a5bc758b308b60cdcea9486976fc15084f107a6";
const LIMIT = 50;
const URL = "https://gateway.marvel.com:443/v1/public/characters";

export const getHash = ts =>


md5(ts + PRIVATE_KEY_MARVEL + PUBLIC_KEY_MARVEL).toString();

function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
const error = new Error(`HTTP Error ${response.statusText}`);
error.status = response.statusText;
error.response = response;
console.log(error);
throw error;
}
}

function parseJSON(response) {
return response.json();
}

const getMarvelComics = () => {


const ts = new Date().getTime();
return fetch(

`${URL}?apikey=${PUBLIC_KEY_MARVEL}&ts=${ts}&hash=${getHash(ts)}&limit=${LIMIT}`,
{
headers: {
Accept: "application/json"
}
}
)
.then(checkStatus)
.then(parseJSON)
.then(res => res.data.results);
};

const getIndividualCharacter = (id) => {


const ts = new Date().getTime();
return fetch(

`${URL}/${id}?apikey=${PUBLIC_KEY_MARVEL}&ts=${ts}&hash=${getHash(ts)}&limit=${LI
MIT}`,
{
headers: {
Accept: "application/json"
}
}
)
.then(checkStatus)
.then(parseJSON)
.then(res => res.data.results);
};

export default { getMarvelComics, getIndividualCharacter };

components/HeroCardList.js

import React, { Component } from 'react';

import HeroCard from './HeroCard';


import api from '../api/api';

class HeroCardList extends Component {


state = {
heroList: []
}

componentDidMount () {
api.getMarvelComics().then((heroList) => {
this.setState({
heroList
});
});
}

render () {
return (
<div className="container">
<div className="row">
<div className="col s12 App-header">
Marvel Comics
</div>
</div>
<div className="row">
{
this.state.heroList.length > 0
?
this.state.heroList.map((hero) => (<HeroCard key={hero.id} hero={hero} />))
:
<h4>Cargando...</h4>
}
</div>
</div>
);
}
}

export default HeroCardList;

components/HeroCard.js

import React from "react";


import { Link } from "react-router-dom";

const HeroCard = props => (


<div className="col s12 m4">
<div className="card blue-grey darken-1">
<div className="card-image">
<img
className="App-image"
src={`${props.hero.thumbnail.path}.${props.hero.thumbnail.extension}`}
alt={props.name}
/>
<span className="card-title bg-card">{props.hero.name}</span>
</div>
<div className="card-action">
<Link to={`/${props.hero.id}`}>More info...</Link>
</div>
</div>
</div>
);

export default HeroCard;

components/Detail.js

import React, { Component } from "react";


import { PUBLIC_KEY_MARVEL, PRIVATE_KEY_MARVEL, getHash } from "../api/api";

import api from "../api/api";

class Detail extends Component {


state = { hero: null };

componentDidMount() {
api.getIndividualCharacter(this.props.match.params.id).then(hero => {
const firstHero = hero[0];
this.setState({
hero: firstHero
});
});
}

render() {
const hero = this.state.hero;
const ts = new Date().getTime();

return (
<div className="container">
<div className="row">
<div className="col s12 App-header">Marvel Description Character</div>
</div>
{hero && (
<div className="row center">
<div className="col s4">
<img
className="detail-image"
src={`${hero.thumbnail.path}.${hero.thumbnail.extension}`}
alt={hero.name}
/>
</div>
<div className="col s8">
<div className="card blue-grey darken-1">
<div className="card-content white-text">
<span className="card-title">{hero.name}</span>
<p>{hero.description}</p>
</div>
{hero.comics.items.length > 0 && (
<div>
<h6 className="detail-comic-list">Comics List</h6>
<div className="collection">
{hero.comics.items.map((comic, idx) => (
<a
key={idx}

href={`${comic.resourceURI}?apikey=${PUBLIC_KEY_MARVEL}&ts=${ts}&hash=${getHash
(ts)}&limit=30`}
target="_blank"
className="collection-item"
>
<span className="badge" />
{comic.name}
</a>
))}
</div>
</div>
)}
</div>
</div>
</div>
)}
</div>
);
}
}

export default Detail;

App.css

.App-header {
display: flex;
font-size: 20px;
background-color: #222;
height: 50px;
padding: 20px;
color: white;
justify-content: center;
align-items: center;
}

.App-image {
height: 300px;
width: 180px;
}

.App-description {
height: 80px;
text-overflow: ellipsis;
overflow: hidden;
}

.bg-card {
display: flex;
justify-content: center;
align-items: center;
font-size: 16px !important;
background: #000;
padding: 16px !important;
height: 20px;
width: 100%;
}

.detail-image {
height: 200px;
width: 200px;
border-radius: 50%;
border: 1px solid #000;
}

.detail-comic-list {
color: white;
font-size: 20px;
}

You might also like