Aprenda los bloques de construcción de React. Conozca React Components.

React no es un framework es una biblioteca de interfaz de usuario (UI) que ha ganado muchos simpatizantes. Un amigo me dijo que no encuentra interesante trabajar con React porque hay demasiadas opciones para realizar una misma funcionalidad. Después de algunas investigaciones me di cuenta que es una de las razones por lo que los desarrolladores se enfrentan a grandes desafíos trabajando con esta librería.

Hay diferentes maneras de crear y administrar un componente de React, toneladas de herramientas de administración de estado emergentes y son el centro de atención de estos desafíos. Lo que podemos hacer hoy es traer la forma más aceptada de hacer las cosas en React (basado en la elección de la comunidad).

A lo largo del camino, visitaremos algunos temas y términos útiles en React que a veces pueden ser intimidantes para los principiantes. Tales temas incluyen:

  • Propiedad de los componentes
  • Validación del Prop
  • Interacción con componentes
  • Valores predeterminados de los componentes
  • ES6 + Componentes (y diferencia con los componentes normales)
  • Componentes Stateless

El componente de React convencional

Por convencional, me refiero a lo que es común y que podría haber visto en la mayoría de los repositorios de código y artículos:

var Hello = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

https://jsfiddle.net/chris92/16o7462z/1/embedded/js,html,result/dark/

Ten en cuenta que convencional no significa la mejor práctica. Esto fue lo que promovió el React oficial y por eso es muy común.

React.createClass función que debe ser pasada con un tipo Object como parámetro. Este objeto define un componente de react. La propiedad render es requerida y la más importante. Es responsable de analizar el código HTML en JavaScript, JSX.

Las aplicaciones Web sólo son interesantes cuando son dinámicas. Cualquier biblioteca de interfaz de usuario siempre proporcionará una forma de pasar datos alrededor del sistema y la idea de React es a través del objeto props. Así que cuando vea el siguiente JSX:

<h1>My name is {name}</h1>

Estamos diciendo que cuando se invoque al componente React cambie el valor de la propiedad en el render.

<Hello name="World" />

El método render coge como salida el DOM. Esto es la forma básica de un componente React.

States & Props

Las aplicaciones dinámicas deben tener que pasar datos a su sistema. En React, el movimiento de datos ocurre principalmente entre componentes y servicios externos que proporcionan los datos originales (por ejemplo, HTTP, localStorage).

Los Props son inmutables y mudos, lo que significa que sólo se pueden pasar de los componentes de los padres hacia abajo y no se puede cambiar. Esto plantea un reto porque, las aplicaciones modernas no dependen de tener todos sus estados listos en la carga de la página. Cuando regresen datos desde Ajax y/o Eventos alguien necesita ser responsable de hacer actualizaciones. Aquí es donde entran los estados React.

Al inicializar React, definimos un estado inicial y mantenemos el estado en sincronía con los Props. Una vez que se actualiza el estado, los accesorios pueden mantenerse fácilmente sincronizados:

var Counter = React.createClass({
    getInitialState: function() {
    return {
        counter: 0
    };
  },
  render: function() {
    return <div>
            <h2>{this.props.name}</h2>
            {this.state.counter}
      </div>;
  }
});

ReactDOM.render(
  <Counter name={'Counter'} />,
  document.getElementById('container')
);

https://jsfiddle.net/chris92/gtwk2ck6/2/embedded/js,html,result/dark/

El ejemplo sigue siendo tonto porque la responsabilidad del Estado en el contexto todavía se puede lograr con los accesorios. Mientras profundizamos, veremos mejores razones para la existencia de estados.

Propiedad de los componentes (a.k.a Parenting)

Esto es bastante sencillo. Si un componente vuelve a renderizar otro componente en su método render, el renderizador es el propietario (padre) del renderizado. El renderizador posee el componente renderizado y tiene control sobre él. Prefiero referirme a esto como crianza de los hijos.

Echemos un vistazo a otro ejemplo:

var CounterDisplay = React.createClass({
    render: function(){
    return <div>{this.props.counterProp}</div>
  }
})

var Counter = React.createClass({
    getInitialState: function() {
    return {
        counter: 0
    };
  },
  render: function() {
    // Child component rendered
    // React will throw an error if the the DOM doesn't have a single parent
    return <div>
            <h2>{this.props.name}</h2>
            <CounterDisplay counterProp={this.state.counter}></CounterDisplay>
      </div>;
  }
});

ReactDOM.render(
  <Counter name={'Counter'} />,
  document.getElementById('container')
);

https://jsfiddle.net/chris92/svad7wrs/2/embedded/js,html,result/dark/

El Counter ahora procesa otro componente, CounterDisplay. Counter es responsable de administrar y sincronizar los apoyos de CounterDisplay. Se puede ver cómo estamos pasando el estado hacia abajo del componente hijo a través de accesorios. Los accesorios (Props) también podrían ser nombrados contadores como el estado, pero esto puede ser muy confuso para los principiantes, así que le di un nombre diferente.

Interacción con componentes

¿Qué sucede si teníamos un botón (o más) en un componente secundario que incrementaba y reducía un entero (estado) administrado en un componente principal. qué hacemos?

En React la interacción del componente viene en dos formas: el flujo de datos del componente del padre al hijo y el flujo de datos del hijo al padre. Ya hemos visto cómo va el flujo de padres a hijos que se logró usando props.

Para lograr el flujo de datos de hijo a padre en React, usamos handlers pasados al componente hijo a través del componente padre como accesorios (props). El padre sabe que tal actividad podría ocurrir en su hijo por lo que establece un manejador para cuando la actividad se produce. Más como eventos:

Component Interaction

var CounterDisplay = React.createClass({
    render: function(){
    // Calls the handler props once events are fired
    return <div>
            <div>{this.props.counterProp}</div>
        <button onClick={this.props.incrementCounter}>+</button>
        <button onClick={this.props.decrementCounter}>-</button>
        </div>
  }
})

var Counter = React.createClass({
    getInitialState: function() {
    return {
        counter: 0
    };
  },
  handleIncrement(){
    // Update counter state
    this.setState({counter : this.state.counter+1});
  },
  handleDecrement(){
      // Update counter state
    this.setState({counter : this.state.counter-1});
  },
  render: function() {
    // Pass down handlers to CounterDisplay component
    return <div>
            <h2>{this.props.name}</h2>
            <CounterDisplay 
            counterProp={this.state.counter}
          incrementCounter={this.handleIncrement}
          decrementCounter={this.handleDecrement}></CounterDisplay>
      </div>;
  }
});

ReactDOM.render(
  <Counter name={'Counter'} />,
  document.getElementById('container')
);

https://jsfiddle.net/chris92/5txjzwzr/embedded/js,html,result/dark/

El componente CounterDisplay tiene eventos click. Sus controladores no se encuentran en ninguna parte del componente. Por el contrario, los manejadores son manejados por el componente principal, Counter. El manejador (handler) a su vez actualiza el estado utilizando el método this.setState() y los elementos de visualización del contador se actualizan sin ser explícitos al respecto.

Valores predeterminados de los componentes

No sólo los estados tienen la capacidad de disfrutar de valores iniciales con el método getInitialState. Si es necesario, también puede configurar los valores predeterminados para los accesorios (props) que se utilizarán en la carga del componente. Para lograr esto, puede hacer uso del método getDefaultProps:

getDefaultProps: function() {
     return {
       name: 'Counter'
     };
},

Esto es muy útil para configurar valores predeterminados en una aplicación.

Validación del Prop

Una cosa buena acerca de los componentes React es que puedes lanzar cualquier componente en tu aplicación para hacer lo que se pretendía hacer siempre y cuando cumplas con su regla. Cuando hago mis propios componentes reutilizables, ¿cómo puedo hacer mis propias reglas? La validación del Prop es la respuesta a la pregunta.

La validación es quien ayuda a asegurar que los datos que fluyen en su componente se estructuran de la forma en que se espera que se estructuren. No puede permitirse el lujo de tratar datos de componentes personalizados como cadena (string) y que el usuario los trate como una matriz (array).

var CounterDisplay = React.createClass({
    render: function(){
    // Calls the handler props once events are fired
    return <div>
            <div>{this.props.counterProp}</div>
        <br />
        <button onClick={this.props.incrementCounter}>+</button>
        <button onClick={this.props.decrementCounter}>-</button>
        </div>
  },
  // Setup validation for each props
  propTypes: {
    // Must be a number
    counterProp: React.PropTypes.number.isRequired,
    // Must be functions
    incrementCounter: React.PropTypes.func.isRequired,
    decrementCounter: React.PropTypes.func.isRequired
   }
})

Si todo lo que necesitas es validar el tipo y no su existencia, puede omitir el isRequired:

propTypes: {
    // Should be a number
    counterProp: React.PropTypes.number,
    // Should be functions
    incrementCounter: React.PropTypes.func,
    decrementCounter: React.PropTypes.func
   }

https://jsfiddle.net/chris92/h96tqfs8/embedded/js,html,result/dark/

Componente de clase (ES6)

React.createClass no es la única forma posible de crear un componente React válido. Con ES6 (que es realmente genial), podemos usar clases para crear componentes React. Esto significa que en lugar de objeto como argumento con propiedades, usamos miembros de clase para definir el comportamiento:

// Extends React.Compoent
class Comment extends React.Component {
 // Render method now a class member rather than
 // object property
  render(){
    return <h1>{this.props.name}</h1>;
  }
}

 React.render(<Comment name={'Comment'}/>, document.getElementById('container'));

El nombre del componente es el nombre de clase y la clase extiende React.Component para heredar sus funcionalidades.

Configuración de estados con Clases

Si vas a la ruta de la clase, las cosas cambiarán. Hay pequeños cambios en la forma en que siempre hemos hecho las cosas, incluyendo el establecimiento de estados iniciales:

class Comment extends React.Component {
   constructor(props) {
        super(props);
        this.state = {
            counter: 0
        };
  }
  render(){
    return <h1>{this.props.name}</h1>;
  }
}

 React.render(<Comment name={'Comment'}/>, document.getElementById('container'));

El estado inicial se establece ahora en el constructor de clase en lugar de utilizar getInitialState. Es importante siempre pasar los apoyos (props) de vuelta a la clase padre utilizando super (props).

Props por defecto y validación con clase

Así como la configuración del estado inicial es diferente, las propiedades predeterminadas y la validación de la propiedad son diferentes. Tratamos los métodos responsables de realizar estas acciones como miembros estáticos de la clase Component que son:

// Validation
Comment.propTypes = {
        counterProp: React.PropTypes.number.isRequired,
    incrementCounter: React.PropTypes.func.isRequired,
    decrementCounter: React.PropTypes.func.isRequired
};
// Defaults
Comment.defaultProps = {
    name: 'Counter'
};

Hay pocas diferencias, pero lo anterior es lo que se debe mirar. Puede leer el artículo de Todd sobre estas diferencias.

Componente sin estado

Cuando un componente no tiene ninguna razón para tratar con estados, es irrelevante usar una clase para definir el componente. Se puede hacer uso de funciones solo si todo es necesario en un componente como prop:

function CommentDisplay(props) {
  return <div>
            <div>{props.counterProp}</div>
        <br />
        <button onClick={props.incrementCounter}>+</button>
        <button onClick={props.decrementCounter}>-</button>
        </div>
}

Es mucho más simple.

Conclusiones

Los temas que hemos cubierto hoy son los que te guiarán al desarrollo real de aplicaciones en React.

 

El manejo del estado en React podría ser complicado y es por eso que existen herramientas como Redux. Con el tiempo, obtendremos tutoriales sobre cómo administrar el estado de aplicaciones React con Redux.

 

Fuente (scotch.io)
Anuncios

Write your comment