React JS
Libreria creada por facebook para renderizar una interface / vista.
Es una libreria declarativa, en lugar de ser imperativa (tal como Ember, Angular).
No usa templating. Usa los ya existentes.
Las interfaces son arbol de componentes, Virtuak DOM.
Interfaces de manera interactiva. No databinding. Alto desempeño. React calcula las modificaciones necesarios para cambiar de una vista a otra.
React permite realizar renderizados en ios, android, web, canvas, terminal (ReactBlest) etc. Por tanto es independiente del renderizado.
Ejemplo : Hola mundo
Creando el html, importar librerias.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Aprendiendo React</title>
</head>
<body>
<div id="content"></div>
<script src="https://fb.me/react-15.0.1.js"></script>
<script src="https://fb.me/react-dom-15.0.1.js"></script>
<script src="app.js"></script>
</body>
</html>
Ahora el archivo app.js que contiene la logica de presentacion.
var app = React.createElement('h1', null, 'Hola mundo!');
ReactDOM.render(app, document.getElementById('content'));
/*
Salida en HTML:
<div id="content">
<h1>Hola mundo!</h1>
</div>
*/
React.createElement(p1,p2,p3)
p1 es el elemento HTML a renderizar, osea el tipo de elemento de DOM
p2 son opciones adicionales, propiedades, atributos children, como {src: 'imagen.png'}. Se pueden pasar todos los atributos conocidos de ese elemento del dom. React esta orientado a ser una API de javascript, por lo que las propiedades deben ser similares (algunas diferencias seria class en HMTL, en react className, style en html y en react es un objeto con propiedades).
p3 es el children , es opcional, puede ser un texto, o hasta otros elementos de dom. Este puede pasarse como segundo parametro igualmente usando el objeto de atributos.
var app = React.createElement('h1', { children: 'Este es un texto' });
ReactDOM.render(app, document.getElementById('content'));
var personas = ['Juan', 'Maria', 'Laura', 'German'];
var app = React.createElement('ul', null,
personas.map(function(persona) {
return React.createElement('li', null, persona);
})
);
ReactDOM.render(app, document.getElementById('content'));
var app = React.createElement('a', {style: {color:'red'}, href: 'https://www.google.com'}, 'Ir a Google');
var app = React.createElement('div', null,
React.createElement("h1", null, 'El titulo'),
React.createElement('p', null, 'Primer Párrafo'),
React.createElement('p', {style: {fontSize:'15px'}} ,'Segundo Párrafo',
React.createElement('a', {href:'https://twitter.com'}, 'Ver más')
));
Componentes
Se pueden hacer propios elementos de DOM.
var app = React.createElement('div', null,
React.createElement('h1', null, 'Mi Sitio - Pagina 1'),
React.createElement('ul', { className: 'menu' },
React.createElement('li', null, 'Inicio'),
React.createElement('li', null, 'Quienes Somos'),
React.createElement('li', null, 'FAQ'),
),
React.createElement('div', { className: 'contenido' },
React.createElement('p', null, 'Mi contenido')
)
);
Hacer funciones propias:
function Encabezado(props) {
return React.createElement(
'h1',
null,
'Mi Sitio - ' + props.nombrePagina
);
}
function Menu() {
return React.createElement('ul', { className: 'menu' },
React.createElement('li', null, 'Inicio'),
React.createElement('li', null, 'Quienes Somos'),
React.createElement('li', null, 'FAQ'),
)
}
function Contenido(props) {
return React.createElement(
'div',
{className: 'contenido'},
props.children
);
}
Ahora la llamada usando funciones queda como:
var app = React.createElement('div', null,
Encabezado({ nombrePagina: 'Pagina 1' }),
Menu(),
Contenido({
children: React.createElement('p', null, 'Mi contenido')
})
);
Al especificarlo en forma React queda como:
var app = React.createElement('div', null,
React.createElement(Encabezado, { nombrePagina: 'Pagina 1'}),
React.createElement(Menu),
React.createElement(Contenido, null,
React.createElement('p', null, 'Mi contenido')
)
);
var app = React.createElement('ul', null,
React.createElement(Tab, { activo: false, href: '#inicio', nombre: 'Inicio'}),
React.createElement(Tab, { activo: true, href: '#quienes-somos', nombre: 'Quienes Somos'}),
React.createElement(Tab, { activo: false, href: '#faq', nombre: 'FAQ'})
);
function Tab(props) {
if (props.activo) {
return React.createElement('li', {className: 'tab tab-activo'},
React.createElement('a', {href:props.href}, props.nombre));
} else {
return React.createElement('li', {className: 'tab'},
React.createElement('a', {href:props.href}, props.nombre));
}
}
Cambiando de funciones a clases
Eliminando la necesidad de funciones, para cambiarlo a clases, que hace al JS mas legible y orientado a objetos.
NOTA: La función render() debe ser PURA, es decir que no haga modificaciones a thos.props y no debe acceder ni causar efectos secundarios, no leer fecha actual, no escribir en bd, ni llamadas ajax. Solo recibe parametros y regresa el componente React.
class Encabezado extends React.Component {
render() {
return React.createElement(
'h1',
null,
'Mi Sitio - ' + this.props.nombrePagina
);
}
}
class Menu extends React.Component {
render() {
return React.createElement(
'ul',
{className: 'menu'},
React.createElement('li', null, 'Inicio'),
React.createElement('li', null, 'Quienes Somos'),
React.createElement('li', null, 'FAQ'),
);
}
}
class Contenido extends React.Component {
render() {
return React.createElement(
'div',
{className: 'contenido'},
this.props.children
);
}
}
Cambiando a forma legacy
Esta forma ya no se usa pero se deja por compatibilidad. Esta es deprecada y se usa en lugar Clases de Js.
var Encabezado = React.createClass({
render: function() {
return React.createElement(
'h1',
null,
'Mi Sitio - ' + this.props.nombrePagina
);
}
});
La diferencia entre padre y dueño: Menu es dueño de ul y li. Pero ul es padre de li.
class Menu extends React.Component {
render() {
return React.createElement('ul', { className: 'menu' },
React.createElement('li', null, 'Inicio'),
React.createElement('li', null, 'Quienes Somos'),
React.createElement('li', null, 'FAQ'),
);
}
}
props
No hay que mutarlas, son solo lectura.
class Boton extends React.Component {
render() {
var color = this.props.color;
if (!color) { color = 'blue'; }
return React.createElement('button', {
style: { color: color }
}, this.props.texto);
}
}
prop children
Se puede definir como el tercer parametro de createElement o puede ser una propiedad del segundo parametro.
class Grilla extends React.Component {
render() {
return React.createElement('div', null,
this.props.children.map(function(elemento) {
return React.createElement('div', null, elemento);
})
);
}
}
Al llamarlo:
var grilla = React.createElement(Grilla, null,
React.createElement(Elemento, null, 'valor 1'),
React.createElement(Elemento, null, 'valor 2'),
React.createElement(Elemento, null, 'valor 3')
);
Error: cuando se manda solo un elemento, el children no es una lista, sino un objeto. La solucion:
class Grilla extends React.Component {
render() {
return React.createElement('div', null,
React.Children.map(this.props.childen,function(elemento) {
return React.createElement('div', null, elemento);
})
);
}
}
React.Children
React.Children.forEach(children, fn);
React.Children.map
React.Children.count(children)
Callback props - comunicandose con el dueño
Un children puede ser tambien una funcion, no solo objetos.
class BotonGuardar extends React.Component {
render() {
return React.createElement('button', {
type: 'button',
onClick: function(ev) {
if (this.props.habilitado) {
this.props.onClick(ev);
}
}.bind(this)
}, 'Guardar');
}
}
class Lista extends React.Component {
render() {
var elementos = this.props.elementos.map(function(elemento) {
return React.createElement(Elemento, { elemento: elemento });
});
if (elementos.length === 0) {
elementos = this.props.renderSinResultados()
}
return React.createElement('div', null,
elementos
);
}
}
// Llamandolo
var app = React.createElement(Lista, {
elementos: [],
renderSinResultados: function () {
return React.createElement(
'p',
null,
'No hay resultados'
);
}
});
Re-render
Usando solo props, aun no tocamos el tema de state.
class Contador extends React.Component {
render() {
return React.createElement('div', null,
React.createElement('p', null, 'La cuenta actual es ', this.props.cuenta),
React.createElement('input', {
type: 'button',
value: 'Incrementar',
onClick: this.props.onIncrementar
}),
React.createElement('input', {
type: 'button',
value: 'Decrementar',
onClick: this.props.onDecrementar
})
);
}
}
// Para renderizar
var node = document.getElementBy('contenido');
function render(cuenta) {
ReactDOM.render(
React.createElement(Contador, {
cuenta: cuenta,
onIncrementar: function() {
render(cuenta + 1);
},
onDecrementar: function() {
render(cuenta - 1);
}
}),
node
);
}
render(0);
ddddd