Andres Bernal

Andres Bernal

Developer.

© 2019

Conceptos de Redux

OOP

REDUX Es una herramienta de administraci贸n de estado se convierte en una necesidad en las aplicaciones React a medida que su estado aumenta en complejidad, una de esas soluciones es Redux.

Redux permite administrar todo el estado de su aplicaci贸n en un objeto, llamado Store.

Las actualizaciones de Store activar谩n la repetici贸n de los componentes que est谩n conectados a la parte de store que se actualiz贸. Cuando queremos actualizar algo, llamamos a una acci贸n. Tambi茅n creamos funciones para manejar estas acciones y devolver la Tienda actualizada. Estas funciones se denominan Reducers.

鈾狅笍 Instalacion de redux

Usamos npm

npm install --save redux 
npm install --save react-redux

La inicializaci贸n de su Store se puede hacer dentro de index.js, o donde llame a ReactDOM.render() a su ID de ra铆z. Para comenzar a utilizar Redux, debemos inicializar Store y usar el componente de Redux para que la Store est茅 disponible para el resto de la aplicaci贸n. Se parece a esto:

//...

import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';

let initialStore = {
};

const store = createStore(rootReducer, initialStore);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>, 
document.getElementById('root'));

//...

鈾狅笍 Acciones & Reductores

Al leer la pagina oficial de Redux, es complejo enteneder sin embargo se encuentra estos conceptos a lo largo de la documentacion que son actions y reducers

Acciones: funciones que devuelven un objeto similar a un objeto JSON que describe algo que suceder谩. Hay una clave obligatoria, tipo de nombre. Debemos dar un tipo a cada acci贸n. Se pueden pasar otros argumentos a una acci贸n que se puede usar para actualizar su Tienda (estado).

Reductores - funciones que manejan acciones y actualizan la tienda. Hacemos esto devolviendo el nuevo estado. Los reductores deben ser funciones puras.

vamos al codigo

鈾狅笍 Acciones

Usaremmos el tipico evento onClick o onSubmit en los que ha enviado un formulario v谩lido.

// login exitoso

{
   type: 'SIGN_IN',  //obligario
   user: username,
   authToken: authToken
});

//username y authToken se pasan a esta acci贸n definition export const setSignIn = (username, authToken) => (

Despu茅s de que un usuario se haya autenticado, se puede llamar a una acci贸n SIGN_IN, donde el authToken y el nombre de usuario se enviar谩n al reductor y Store en el estado

// cerrar sesion
// no se pasa nada solo se necesita el reductor
// mi autenticacion de usuario
export const setSignOut = () => (
{
 type: 'SIGN_OUT'
});

Lo anterior es un ejemplo de salir de la aplicaci贸n. Esta acci贸n activar谩 mi reducer para eliminar algunas credenciales que se encuentran actualmente en estado. Recuerde, su store es de solo lectura, la 煤nica forma de actualizarla es a trav茅s de Acciones y reductores.


// cambiar la barra de progreso
// el  estado aqu铆 puede ser OCULTAR o MOSTRAR
export const setProgressBar = (status) => (
{
 type: 'SET_PROGRESS_BAR',
 status: status
});

En las siguiente plantilla eguir, dar茅 una estructura de proyecto de Redux y c贸mo integrar acciones a su proyecto.

鈾狅笍 Reducer

Los reductores reaccionan a las llamadas de acci贸n (o dispatches) y las manejan en consecuencia. Los documentos de Redux lo alientan a usar instrucciones de cambio para manejar cada acci贸n dentro de su reductor. Tambi茅n puede definir varios reductores en archivos separados para mantener su c贸digo organizado. Los reductores devuelven el nuevo estado actualizado.

se organizan de la siguiente manera

src/
   reducers/
      index.js
      ui.js
      auth.js
      ...

En esta configuraci贸n, ui.js y auth.js manejar谩n acciones relacionadas con los cambios y la autenticaci贸n de la interfaz de usuario. La IU es bastante vaga, pero incluir铆a cosas como manejar la barra de progreso de tu aplicaci贸n. auth.js manejar铆a un tipo de acci贸n SIGN_IN o un tipo de acci贸n **SIGN_OUT, y no olvidemos la verificaci贸n de tokens de autenticaci贸n v谩lidos en una actualizaci贸n de p谩gina o una nueva visita, una acci贸n para la que podr铆a llamarse AUTHENTICATE_TOKEN.

index.js no define m谩s reductores, y en su lugar combina ui.js y auth.js usando la funci贸n combineReducers() de Redux

Para demostrar un reductor, reducers / ui.js puede manejar nuestra acci贸n de la barra de progreso, de esta manera:

// un reductor es solo una declaraci贸n de cambio que maneja cada acci贸n que definimos.
// un reductor devuelve el nuevo estado, que a su vez actualiza Store.
export const ui = (state = {}, action) => {
   switch (action.type) {
      
      case 'SET_PROGRESS_BAR':
         return Object.assign({}, state, { progressBarStatus: action.status });
  
  
      default:
        return state;
   }
};
export default ui

//



Este reductor devuelve un nuevo estado con un cambio: el progressBarStatus se actualiza a nuestro valor action.status.
Nota: Si nuestro estado est vaco, le damos un valor inicial de un objeto vaco, {}.
Para incluir este reductor en nuestro archivo de ndice (o raz), hacemos lo siguiente:



**reducers/index.js:**

```javascript
import { combineReducers } from 'redux';
import ui from './ui';
import auth from './auth';
export default combineReducers({
   ui,
   auth,
});

Aqu铆 solo tenemos 2 reductores, pero a medida que su aplicaci贸n crezca, puede agregar f谩cilmente m谩s dentro de combineReducers(). Probablemente pueda ver lo que est谩 sucediendo aqu铆: en cada llamada de acci贸n (o env铆o), el tipo de acci贸n pasa a trav茅s de todos nuestros archivos reductores. Si el tipo de acci贸n no coincide con cada instrucci贸n de cambio, el caso predeterminado simplemente devuelve el estado actual.

Dispatch la forma de llamar a las acciones

Es otra funci贸n de Redux que usamos para llamar acciones. Podemos definir un despacho de acci贸n as铆:

 const dispatchSetSignedIn = dispatch(setSignedIn(username, authToken));

Ahora podemos usar dispatchSetSignedIn* en un evento onClick, por ejemplo, que a su vez pasar铆a por el canal de Redux:

setSignedIn devuelve nuestra definici贸n de acci贸n en formato JSON dispatchSetSignedIn enviar谩 nuestra acci贸n a nuestros Reductores action.type se prueba para cada instrucci贸n de cambio de los archivos de Reducer. Cuando se encuentra el correcto, devuelve un estado actualizado Nuestros componentes conectados al estado actualizado se volver谩n a representar. Veamos c贸mo hacerlo en la 煤ltima pieza del rompecabezas Redux.

Conectando componentes a STORE

Conectar componentes al Store es bastante sencillo. Para explicar la manera est谩ndar de codificar esto, vamos a referirnos a una ideolog铆a de tipo componente: Contenedor y Presentaci贸n.

Concretamente, se crea un componente separado para que act煤e como el contenedor del componente al que deseamos conectar nuestra Store. El componente al que deseamos conectar el estado se convierte en nuestro componente de presentaci贸n.

  • Componente contenedor: maneja la l贸gica: el componente al que enviamos las URL. Aqu铆 no se representa nada.
  • Componente de presentaci贸n: UI al contenedor. El componente Contenedor conecta este componente con 茅l, por lo tanto, procesa este componente.

La forma en que se pasa el estado a su componente de presentaci贸n es a trav茅s de accesorios. Por lo tanto, nos referimos a this.props, y no this.state al obtener nuestros datos de estado conectados en la presentaci贸n.

C贸mo se conecta un componente de presentaci贸n a un componente contenedor

Redux proporciona 2 funciones de utilidad que podemos utilizar para pasar props y acciones en nuestro componente de presentaci贸n:

  • mapStateToProps: conecta el estado como accesorios al componente (de nuevo, el estado de tu tienda est谩 conectado a trav茅s de los props )
  • mapDispatchToProps: env铆o de acciones como accesorios, lo que nos permite llamar a acciones dentro del componente.

Estas dos funciones de utilidad se definen por separado, seguidas de su componente contenedor. Veamos brevemente una plantilla antes de un ejemplo completo:


import { connect } from 'react-redux';

//Presentational component
class MyComponent extends Component {
   
   render() {
      ...
   }
}
//estado:  nuestro estado se pasa como el primer argumento aqu铆
const mapStateToProps = (state, ownProps) => {
}
//Actions: La funci贸n de despacho de Redux se pasa como el primer argumento aqu铆
const mapDispatchToProps = (dispatch, ownProps) => {
}
//definiendo el componente Contenedor, pasando las 2 funciones anteriores a connect () de Redux.
export const MyComponentContainer = connect(
 mapStateToProps,
 mapDispatchToProps
)(MyComponent);
export default MyComponentContainer

Por lo tanto, todo se pasa del componente contenedor al componente de presentaci贸n. Una implementaci贸n completa de un componente de Presentaci贸n y Contenedor se define as铆:

import { connect } from 'react-redux';

//Presentational component
class MyComponent extends Component {
   
	render() {
		//...
	}
}
  
//state a props 
const mapStateToProps = (state, ownProps) => {
return({
		itemState: state.someValue,
	});
};

//dispatch actions a props
const mapDispatchToProps = (dispatch, ownProps) => {
	return({
		handleAction: arg => dispatch(setMyAction(arg)),
	});
};

//Container component
export const MyComponentContainer = connect(
	mapStateToProps,
	mapDispatchToProps
)(MyComponent);

export default MyComponentContainer

Echa un vistazo a los siguientes puntos sobre este fragmento de c贸digo

ownProps se pasa a trav茅s de mapStateToProps y mapDispatchToProps, y se usa para acceder a las propiedades definidas por el componente principal de MyComponentContainer

Dentro de mapDispatchToProps, se est谩n definiendo los accesorios que llaman a las acciones. Usamos dispatch() alrededor de la acci贸n para llamarla, en este caso, cuando se llama handleAction en la presentaci贸n. No est谩 obligado a definir mapStateToProps o mapDispatchToProps. En el caso de que no necesite uno o ambos, reempl谩celos con null en su connect(). No mezcle el orden: si solo desea definir mapDispatchToProps, coloque un nulo antes de mantener su segunda ubicaci贸n de argumento

MyComponent y MyContainerComponent pueden ser nombrados como desees. El uso del controlador despu茅s del nombre del componente de presentaci贸n es com煤n, por ejemplo, Iniciar sesi贸n y iniciar sesi贸nHandler, Home y HomeHandler. Otra sugerencia es usar Handle antes del nombre del componente, por ejemplo, HandleLogin y Login

鈾狅笍 Uniendo Todo

Para poner todo junto, el resto de este art铆culo le proporciona algunas plantillas para inyectar directamente en su proyecto para comenzar con Redux. Puede copiar y pegar estos fragmentos de c贸digo en su proyecto como punto de partida para obtener una estructura Redux que funcione. Cree la siguiente estructura de proyecto para nuestra configuraci贸n de Redux:


src/
   actions/
      index.js
   
   components/
      MyComponent.js
   
   reducers/
      index.js
      ui.js

La siguiente informaci贸n contiene nuestra configuraci贸n inicial de Redux:


/*
 * src/actions/index.js
 */

// no limitado a un solo argumento
export const setActionTemplate = (itemId) => (
{
 type: 'SET_ACTION_TYPE',
 itemId: itemId
});


// Redux tambi茅n sugiere definir constantes para sus tipos de acci贸n.
export const setActionTypes = {
 SET_ACTION_TYPE: 'SET_ACTION_TYPE'
};

/*
 * src/components/MyComponent.js
 */

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { setActionTemplate} from '../actions';
//component
class MyComponent extends Component {

render() {

 const handleOnClick = () => {
   this.props.handleOnClick('your-item-id');
 };

 return(
   <div>
    <h1>My Component</h1>
    <p><a onClick={this.handleOnClick}>Dispatch Action</a></p>
    <p>Current item ID: { this.props.itemId }</p>
   </div>
  )
 }
}

//redux configuration:
const mapStateToProps = (state, ownProps) => {
return({
   itemId: state.itemId
 });
};
const mapDispatchToProps = (dispatch, ownProps) => {
return({
   handleOnClick: itemState => dispatch(setActionTemplate(ownProps.prop))
 });
};

export const MyComponentContainer = connect(
 mapStateToProps,
 mapDispatchToProps
)(MyComponent);

export default MyComponentContainer



/*
 * index.js (your root DOM render)
 * Agregue el c贸digo de Redux aqu铆 en lugar de reemplazar su archivo completo.
 */

import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';

let initialStore = {
   itemId: 1
};

const store = createStore(rootReducer, initialStore);

ReactDOM.render(
   <Provider store={store}>
    <App />
   </Provider>,
 
document.getElementById('root'));


/*
 * src/reducers/childReducer.js
 */

export const childReducer = (state = {}, action) => {

  let newState;

  switch (action.type) {
   case 'SET_ACTION_TYPE':
      
     newState = Object.assign({}, { someValue: action.itemId);
     return newState;
   
   //define more cases as your project builds.
   default:
     return state;
 }
};
                            
export default childReducer


/*
 * src/reducers/index.js
 */

import { combineReducers } from 'redux';
import childReducer from './childReducer';

//import and add more child reducers as your project builds.
export default combineReducers({
 childReducer,
});

Listo, hasta aqui llega mi post,hasta la proxima!!