Skip to content

Latest commit

 

History

History
300 lines (223 loc) · 18.9 KB

README_es.md

File metadata and controls

300 lines (223 loc) · 18.9 KB

Logo de Redux saga en panorama

redux-saga

npm version CDNJS npm Discord Shield OpenCollective OpenCollective

redux-saga es una librería hecha con la intención de facilitar el manejo de efectos secundarios (side effects) (ej. operaciones asíncronas como la obtención de datos (data fetching) y cosas impuras como el acceso al cache del navegador), de manera más eficiente, más simple de probar, y para mejorar el manejo de fallas.

El modelo mental es que una saga represente (a manera de simulación) un hilo diferente en la aplicación y que únicamente sea responsable de los efectos secundarios. redux-saga es un middleware (capa intermedia) de redux, lo que significa que este "hilo" puede ser iniciado, suspendido, y cancelado desde la aplicación principal con una acción cualquiera de redux, tiene acceso a todo el estado (state) de la aplicación en redux y también puede ejecutar (dispatch) acciones en redux.

Usa una de las caracteristicas de ES6 llamada Generadores (Generators) para que procedimientos o operaciones asíncronas sean fáciles de leer, escribir y probar. (Sí no estás familirizado con generadores aquí hay algúnos enlaces introductorios en inglés) Al usar estos generadores, estas opreaciones asíncronas se asemejan a código común y corriente síncrono en JavaScript. (Algo así como async/await, pero los generadores tienen algúnas ventajas adicionales excelentes que necesitamos)

Es posible que ya hayas usado redux-thunk para manejar la obtención de datos en tu aplicación. Contrario a redux-thunk, aquí no necesitarás llenar tu aplicación de callback hells, también podrás probar tus operaciones asíncronas de manera sencilla y tus acciones en redux se mantendrán puras(pure actions).

Getting started

Instalación

$ npm install --save redux-saga

o

$ yarn add redux-saga

También puedes usar los builds UMD que se encuentran directamente en el tag <script> de una página HTML. Ve esta sección.

Ejemplo de uso

Imagina que tienes un UI que necesita solicitar datos de un servidor cuando un botón en pantalla es presionado. (Por simplicidad solo te mostraremos la acción que ejecutará el código)

class UserComponent extends React.Component {
  ...
  onSomeButtonClicked() {
    const { userId, dispatch } = this.props
    dispatch({type: 'USER_FETCH_REQUESTED', payload: {userId}})
  }
  ...
}

El Componente envía (dispatches) un objeto de una acción hacia el Store (almacén de datos). Crearemos una Saga que observe todas las acciones de tipo USER_FETCH_REQUESTED y que ejecute una llamada de API para solicitar los datos del usuario.

sagas.js

import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
import Api from '...'

// Saga: será ejecutada cuando la acción USER_FETCH_REQUESTED sea envíada/ejecutada
function* fetchUser(action) {
  try {
    const user = yield call(Api.fetchUser, action.payload.userId)
    yield put({ type: 'USER_FETCH_SUCCEEDED', user: user })
  } catch (e) {
    yield put({ type: 'USER_FETCH_FAILED', message: e.message })
  }
}

/*
  Llama a fetchUser cada vez que la acción `USER_FETCH_REQUESTED` es enviada/ejecutada.
  `takeEvery` permite que las peticiones se ejecuten de manera concurrente.
*/
function* mySaga() {
  yield takeEvery('USER_FETCH_REQUESTED', fetchUser)
}

/*
  Igualmente podrías usar `takeLatest`.

  No permite solicitudes concurrentes del mismo tipo de accion. Si una accion de tipo `USER_FETCH_REQUESTED`
  se envía mientras otra está está siendo ejecutada en ese preciso momento, la acción que está siendo ejecutada será cancelada y sólo la última en recibirse será ejecutada.
*/
function* mySaga() {
  yield takeLatest('USER_FETCH_REQUESTED', fetchUser)
}

export default mySaga

Para ejecutar una Saga, necesitamos conectarla a un Redux Store (almacén de datos Redux) usando redux-saga como un middleware.

main.js

import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'

import reducer from './reducers'
import mySaga from './sagas'

// creamos el saga middleware
const sagaMiddleware = createSagaMiddleware()
// lo montamos en la Redux Store
const store = createStore(reducer, applyMiddleware(sagaMiddleware))

// y se inicia la saga
sagaMiddleware.run(mySaga)

// por último se muestra la aplicación

Documentación

Traducciones

Usando umd en el navegador

Además de npm y yarn, existe una distribución umd de redux-saga y se encuentra disponible en la carpeta dist/. Cuando se utilice un build umd de redux-saga este estará disponible como ReduxSaga en el objeto window. Esto permite que se pueda create un Saga middleware sin necesidad de usar un import de ES6, esto funciona de la siguiente manera:

var sagaMiddleware = ReduxSaga.default()

La versión umd es útil si no se utiliza Webpack o Browserify. Se puede encontrar directamente en unpkg.

Los siguientes builds están disponibles:

¡Importante! Si el navegador que utilizara la aplicación no tiene soporte para generadores de ES2015, se deberá transpilarlos (ej. con el plugin babel) y proveer un runtime válido, como este. Este runtime debe ser importado antes de importar redux-saga:

import 'regenerator-runtime/runtime'
// después
import sagaMiddleware from 'redux-saga'

Compilado desde el código fuente

$ git clone https://github.com/redux-saga/redux-saga.git
$ cd redux-saga
$ yarn
$ npm test

Más abajo podrás encontrar ejemplos portados (hasta el momento) de los repos de Redux.

Ejemplos de contadores

Hay tres ejemplos de contadores.

contador-vainilla (vanilla JavaScript)

Demo usando vanilla JavaScript y builds UMD. Todo el código fuente está escrito directamente en index.html.

Para ejecuta el ejemplo, solo abre index.html en tu navegador.

Importante: tu navegador debe contar con soporte para generadores. Las últimas versiones de Chrome/Firefox/Edge tienen el soporte necesario.

counter

Demo usando webpack y el API de alto nivel takeEvery.

$ npm run counter

# probar el generador de ejemplo
$ npm run test-counter

cancellable-counter

Demo usando un API de bajo nivel que demuestra como cancelar una tarea.

$ npm run cancellable-counter

Ejemplo de un carrito de compras

$ npm run shop

# probar el generador de ejemplo
$ npm run test-shop

Ejemplo asíncrono

$ npm run async

# probar el ejemplo de generadores
$ npm run test-async

Ejemplo de una situación real (con webpack y hot reloading)

$ npm run real-world

# lo siento, aún no se implementan las pruebas

TypeScript

Redux-Saga con TypeScript requieren de DOM.Iterable o ES2015.Iterable. Si tu target es ES6, es posible que estés listo, sin embargo, si pleaneas ejecutarlo en una ambiente ES5 necesitarás añadirlo por tu cuenta. Revisa tu archivo tsconfig.json, y la documentación oficial para las opciones del compilador.

Logo

El logo oficial de Redux-Saga en diferentes estilos lo puedes encontrar en el directorio de logos.

Backers

Por favor, apoyanos con una donación mensual para seguir seguir con nuestras actividades. [Convertirme en backer]

Patrocinadores

Conviertete en patrocinador y pon tu logo en nuestro README en Github con un enlace a tu sitio. [Convertirme en patrocinador]