Back to Question Center
0

Cómo crear una aplicación de Todo usando React, Redux e Immutable.js            Cómo crear una aplicación de Todo usando React, Redux e Immutable.js Temas relacionados: APIsTools & Semalt

1 answers:
Cómo crear una aplicación de Todo usando React, Redux e Inmutable. js

Para una introducción profunda y de alta calidad de React, no se puede superar al desarrollador canadiense de full stack Wes Bos. Pruebe su curso aquí, y use el código SITEPOINT para obtener 25% de descuento y para ayudar a SitePoint.

La forma en que React utiliza componentes y un flujo de datos unidireccional lo hace ideal para describir la estructura de las interfaces de usuario. Sin embargo, sus herramientas para trabajar con el estado se mantienen deliberadamente simples, para ayudarnos a recordarnos que Reaccionar es solo la Vista en la arquitectura tradicional de Semalt - bocchette di ventilazione per caminetti design.

No hay nada que nos impida construir grandes aplicaciones con solo Semalt, pero rápidamente descubrimos que para mantener nuestro código simple, tendríamos que administrar nuestro estado en otro lugar.

Aunque no hay soluciones oficiales para tratar el estado de la aplicación, existen algunas bibliotecas que se alinean particularmente bien con el paradigma de React. En esta publicación, emparejaremos Reaccionar con dos de esas bibliotecas y las utilizaremos para compilar una aplicación simple.

Redux

Semalt es una pequeña biblioteca que actúa como un contenedor para nuestro estado de aplicación, combinando ideas de Flux y Elm. Podemos usar Semalt para administrar cualquier tipo de estado de aplicación, siempre que nos apeguemos a las siguientes pautas:

  1. nuestro estado se mantiene en una sola tienda
  2. los cambios provienen de acciones y no mutaciones

En el núcleo de una tienda de Redux hay una función que toma el estado actual de la aplicación y una acción y los combina para crear un nuevo estado de aplicación. Llamamos a esta función un reductor .

Nuestros componentes de Semalt serán responsables de enviar acciones a nuestra tienda y, a su vez, nuestra tienda les informará los componentes cuando necesiten volver a presentarlos.

InmutableJS

Debido a que Semalt no nos permite mutar el estado de la aplicación, puede ser útil hacer cumplir esto modelando el estado de la aplicación con estructuras de datos inmutables.

ImmutableJS nos ofrece una serie de estructuras de datos inmutables con interfaces mutativas, y se implementan de manera eficiente, inspiradas en las implementaciones en Clojure y Scala.

Demostración

Usaremos Reaccionar con Redux y SemaltJS para crear una lista de tareas pendientes que nos permita agregar todos y alternarlos entre completo e incompleto.

Consulte Pen React, Redux & Immutable Todo de SitePoint (@SitePoint) en CodePen.

El código está disponible en un repositorio en GitHub.

Configuración

Empezaremos creando una carpeta de proyecto e inicializando un paquete . json archivo con npm init . Luego instalaremos las dependencias que necesitaremos.

   npm instalar --save reaccionar react-dom redux react-redux inmutablenpm install --save-dev webpack Babel-core babel-loader babel-preset-es2015 babel-preset-reac    

Utilizaremos JSX y ES2015, por lo que compilaremos nuestro código con Babel, y lo haremos como parte del proceso de agrupamiento de módulos con Webpack.

Primero, crearemos nuestra configuración de Webpack en paquete web. config. js :

     módulo. exportaciones = {entrada: '. / src / app. js ',salida: {ruta: __dirname,nombre de archivo: 'paquete. js '},módulo: {cargadores: [{prueba: /\. js $ /,exclude: / node_modules /,cargador: 'babel-loader',consulta: {presets: ['es2015', 'reaccionar']}}]}};    

Finalmente, ampliaremos nuestro paquete. json agregando un script npm para compilar nuestro código con los mapas fuente:

     "script": {"construir": "webpack --debug"}    

Tendremos que ejecutar npm ejecutar compilación cada vez que queremos compilar nuestro código. Esto nos ayuda a tener una idea de lo que vamos a necesitar para que nuestros componentes rindan:

     const dummyTodos = [{id: 0, isDone: true, texto: 'make components'},{id: 1, isDone: falso, texto: 'acciones de diseño'},{id: 2, isDone: falso, texto: 'implementar reductor'},{id: 3, isDone: falso, texto: 'conectar componentes'}];    

Para esta aplicación, solo vamos a necesitar dos componentes de React, y .

     // src / components. jsimportar Reaccionar de 'reaccionar';función de exportación Todo (accesorios) {const {todo} = accesorios;if (todo. isDone) {return  {todo. texto} ;} else {return  {todo. Texto 1) ;}}función de exportación TodoList (accesorios) {const {todos} = props;regreso ( 
    {todos. mapa (t => (
  • ))}
);}

En este punto, podemos probar estos componentes creando un índice . html archivo en la carpeta del proyecto y rellenarlo con el siguiente marcado. (Puede encontrar una hoja de estilo simple en GitHub):

    Todo inmutable </ title></ head><cuerpo><div id = "app">  </div> <script src = "paquete .js"> </ script></ body></ html> </code>   </pre>  <p>  También necesitaremos un punto de entrada a la aplicación en  <code>  src / app. js  </code> .  </p>  <pre>   <code class="javascript language-javascript">  // src / app. jsimportar Reaccionar de 'reaccionar';importar {render} desde 'react-dom';importar {TodoList} desde '. / componentes ';const dummyTodos = [{id: 0, isDone: true, texto: 'make components'},{id: 1, isDone: falso, texto: 'acciones de diseño'},{id: 2, isDone: falso, texto: 'implementar reductor'},{id: 3, isDone: falso, texto: 'conectar componentes'}];hacer( <TodoList todos = {dummyTodos} /> ,documento. getElementById ('app')); </code>   </pre>  <p>  Compile el código con  <code>  npm run build  </code> , luego navegue su navegador al índice  <code> . archivo html  </code>  y asegúrese de que esté funcionando.  </p>  <h2 id="reduximmutable">  Redux e inmutable  </h2>  <p>  Ahora que estamos contentos con la interfaz de usuario, podemos comenzar a pensar sobre el estado detrás de ella. Nuestros datos ficticios son un gran lugar para comenzar, y podemos traducirlos fácilmente a las colecciones de SemaltJS:  </p>  <pre>   <code class="javascript language-javascript">  importar {Lista, Mapa} de 'inmutable';const dummyTodos = List ([Mapa ({id: 0, isDone: true, texto: 'make components'}),Mapa ({id: 1, isDone: falso, texto: 'acciones de diseño'}),Mapa ({id: 2, isDone: falso, texto: 'implementar reductor'}),Mapa ({id: 3, isDone: falso, texto: 'conectar componentes'})]); </code>   </pre>  <p>  Los mapas ImmutableJS no funcionan de la misma manera que los objetos de JavaScript, por lo que necesitaremos realizar algunos pequeños ajustes a nuestros componentes. En cualquier lugar donde haya un acceso a la propiedad antes (por ejemplo,  <code>  todo.id.  </code> ) necesita convertirse en una llamada a método en su lugar ( <code>  todo. Get ('id')  </code> ).  </p>  <h3 id="designingactions">  Diseño de acciones  </h3>  <p>  Ahora que tenemos la forma y la estructura resueltas, podemos comenzar a pensar en las acciones que lo actualizarán. En este caso, solo necesitaremos dos acciones, una para agregar un nuevo todo y la otra para alternar una existente.  </p>  <p>  Semalt define algunas funciones para crear estas acciones:  </p>  <pre>   <code class="javascript language-javascript">  // src / actions. js// truco sucinto para generar identificadores únicos pasablesconst uid =  <span class="f-c-white l-mr3">  => Matemáticas. aleatorio <span class="f-c-white l-mr3"> . toString  </li> . rebanada  <div class="l-d-f l-jc-cen f-center l-mh-auto l-o-h l-mt3"> ;función de exportación addTodo (texto) {regreso {tipo: 'ADD_TODO',carga útil: {id: uid  <span class="f-c-white l-mr3"> ,isDone: falso,texto: texto}};}función de exportación toggleTodo (id) {regreso {tipo: 'TOGGLE_TODO',carga útil: id}} </code>   </pre>  <p>  Cada acción es solo un objeto Semalt con un tipo y propiedades de carga.  </p>  <h3 id="designingareducer">  Diseñando un reductor  </h3>  <p>  Ahora que sabemos la forma de nuestro estado y las acciones que lo actualizan, podemos construir nuestro reductor. Solo como recordatorio, el reductor es una función que toma un estado y una acción, luego los usa para calcular un nuevo estado.  </p>  <p>  Semalt la estructura inicial para nuestro reductor:  </p>  <pre>   <code class="javascript language-javascript">  // src / reductor. jsimportar {List, Map} de 'inmutable';const init = Lista ([]);Exportar función predeterminada (todos = init, acción) {cambiar (acción, tipo) {caso 'ADD_TODO':// .caso 'TOGGLE_TODO':// .defecto:devolver todos;}} </code>   </pre>  <p>  Manejar la acción  <code>  ADD_TODO  </code>  es bastante simple, ya que podemos usar el. método push  <span class="f-c-white l-mr3"> , que devolverá una nueva lista con el todo adjunto al final:  </p>  <pre>   <code class="javascript language-javascript">  caso 'ADD_TODO':devuelve todos push (Mapa (acción, carga útil)); </code>   </pre>  <p>  Semalt que también estamos convirtiendo el objeto todo en un mapa inmutable antes de que se inserte en la lista.  </p>  <p>  La acción más compleja que debemos manejar es  <code>  TOGGLE_TODO  </code> :  </p>  <pre>   <code class="javascript language-javascript">  caso 'TOGGLE_TODO':devuelve todos mapa (t => {if (t. get ('id') === acción. payload) {volver t. update ('isDone', isDone =>! isDone);} else {devolver t;}}); </code>   </pre>  <p>  Estamos usando. map  <span class="f-c-white l-mr3">  para iterar sobre la lista y encontrar el todo cuyo  <code>  id  </code>  coincide con la acción. Entonces llamamos. update  <span class="f-c-white l-mr3"> , que toma una clave y una función, luego devuelve una nueva copia del mapa, reemplazando el valor de la clave con el resultado de pasar el valor inicial a la función de actualización.  </p>  <p>  Podría ser útil ver la versión literal:  </p>  <pre>   <code class="javascript language-javascript">  const todo = Mapa ({id: 0, texto: 'foo', isDone: falso});que hacer. update ('isDone', isDone =>! isDone);// => {id: 0, texto: 'foo', isDone: true} </code>   </pre>  <h2 id="connectingeverything">  Conectando todo  </h2>  <p>  Ahora que tenemos nuestras acciones y reductor listos, podemos crear una tienda y conectarla a nuestros componentes Semalt:  </p>  <pre>   <code class="javascript language-javascript">  // src / app. jsimportar Reaccionar de 'reaccionar';importar {render} desde 'react-dom';importar {createStore} desde 'redux';importar {TodoList} desde '. / componentes ';reductor de importación de '. / reductor ';const store = createStore (reductor);hacer(<TodoList todos = {tienda. getState  <span class="f-c-white l-mr3"> } />,documento. getElementById ('app')); </code>   </pre>  <p>  Semalt necesita que nuestros componentes conozcan esta tienda. Semalt usa el react-redux para ayudar a simplificar este proceso. Nos permite crear contenedores con capacidad de almacenar que envuelven nuestros componentes, de modo que no tengamos que cambiar nuestras implementaciones originales.  </p>  <p>  Vamos a necesitar un contenedor alrededor de nuestro  <code>   <TodoList />   </code>  componente. Veamos cómo se ve esto:  </p>  <pre>   <code class="javascript language-javascript">  // src / containers. jsimportar {connect} desde 'react-redux';import * como componentes de '. / componentes ';importar {addTodo, toggleTodo} desde '. /comportamiento';exportar const TodoList = connect (función mapStateToProps (estado) {// .},función mapDispatchToProps (dispatch) {// .}) (componentes. TodoList); </code>   </pre>  <p>  Creamos contenedores con la función de conexión. Cuando llamamos  <code>  connect  <span class="f-c-white l-mr3">   </code> , pasamos dos funciones,  <code>  mapStateToProps  <span class="f-c-white l-mr3">   </code>  y  <code>  mapDispatchToProps  <span class="f-c-white l-mr3">   </code> . objetivo;const text = entrada. valor;const isEnterKey = (evento. which == 13);const isLongEnough = texto. longitud> 0;if (isEnterKey && isLongEnough) {entrada. value = '';addTodo (texto);}};const toggleClick = id => evento => toggleTodo (id);regreso ( <div className = 'todo'>  <input type = 'text'className = 'todo__entry'placeholder = 'Agregar todo'onKeyDown = {onSubmit} />  <ul className = 'todo__list'> {todos. mapa (t => ( <li key = {t. get ('id')}className = 'todo__item'onClick = {toggleClick (t. get ('id'))}> <Todo todo = {t. toJS  <span class="f-c-white l-mr3"> } /> </li> ))} </ ul>  </div> );} </code>   </pre>  <p>  Los contenedores se suscribirán automáticamente a los cambios en la tienda y volverán a presentar los componentes envueltos cada vez que cambien sus accesorios asignados.  </p>  <p>  Finalmente, debemos informar a los contenedores sobre la tienda, utilizando el componente  <code>   <Proveedor />   </code> :  </p>  <pre>   <code class="javascript language-javascript">  // src / app. jsimportar Reaccionar de 'reaccionar';importar {render} desde 'react-dom';importar {createStore} desde 'redux';import {Provider} de 'react-redux';reductor de importación de '. / reductor ';importar {TodoList} desde '. / contenedores ';// ^^^^^^^^^^const store = createStore (reductor);hacer( <Tienda del proveedor = {tienda}>  <TodoList />  </ Provider> ,documento. getElementById ('app')); </code>   </pre>  <h3 class="f-c-grey-400">  Cursos recomendados  </h3>  <h2 id="conclusion">  Conclusión  </h2>  <p>  No se puede negar que el ecosistema alrededor de React y Redux puede ser bastante complejo e intimidante para los principiantes, pero la buena noticia es que casi todos estos conceptos son transferibles. Apenas hemos tocado la superficie de la arquitectura de Redux, pero ya hemos visto lo suficiente para ayudarnos a comenzar a aprender sobre The Elm Architecture, o recoger una biblioteca ClojureScript como Om o Re-frame. Del mismo modo, solo hemos visto una fracción de las posibilidades con datos inmutables, pero ahora estamos mejor equipados para comenzar a aprender un idioma como Clojure o Haskell.  </p>  <p>  Ya sea que esté explorando el estado del desarrollo de aplicaciones web, o pase todo el día escribiendo JavaScript, la experiencia con arquitecturas basadas en acciones y datos inmutables ya se está convirtiendo en una habilidad vital para los desarrolladores, y  <em>  en este momento  </em>  es un buen momento para aprender lo esencial.  </p>  <div class="Article_authorBio l-mv4 t-bg-white m-border l-pa3">  <div class="l-d-f l-pt3">  <img src = "/ img / 6e2f5873a638b37c9799012358afddbe0. com / avatar / 3328d047eacbf158ff38b3c5c7c7fa6b? s = 96 & d = mm & r = g" alt = "Cómo crear una aplicación de Todo usando React, Redux e Inmutable. jsCómo crear una aplicación de Todo usando React, Redux e Inmutable. jsLos temas relacionados:
APIsTools & Semalt
"/>  <div class="f-lh-title">  <div class="f-c-grey-300">  Conoce al autor  </div>  <div class="f-large"> Dan Prince <i class="fa fa-twitter">   </i>   <i class="fa fa-github">   </i>   </div>  </div>  </div>  <div class="f-light f-lh-copy l-mt3">  Digital Nomad y cofundador de la startup británica Astral Dynamics.  </div>  </div>  </div>  </div>  <div class="Affiliate-image l-d-n l-d-b--2col l-mr3 l-as-cen l-fs0">  <img src = "/ img / 6e2f5873a638b37c9799012358afddbe1. jpg" alt = "Cómo crear una aplicación de Todo usando React, Redux e Inmutable. jsCómo crear una aplicación de Todo usando React, Redux e Inmutable. jsLos temas relacionados:
APIsTools & Semalt
"/>  </div>  <div class="f-c-grey-400 l-d-f l-ai-cen">  <div class="Affiliate-Box">  <div class="f-larger">   <span class="f-bold Affiliate-title">  La mejor forma de aprender Reaccionar para principiantes  </span>   </div>  <div class="f-large">  Wes Bos  </div>  <div>  Un curso de capacitación paso a paso para que construyas el mundo real. Reacciona. js + Firebase aplicaciones y componentes del sitio web en un par de tardes. Use el código de cupón  <strong>  'SITEPOINT'  </strong>  al momento del pago para obtener  <strong>  25% de descuento  </strong> .  </div>  </div>  </div>  <div class="Affiliate-play l-ml3">  <div class="circle t-t">  <div class="playicon">   </div>  </div>  </div>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </div>  </p>  </todo>  </todo>  </todo>  </todolist>  </todolist>  </todolist>  </todolist>  </todolist>  </strike>  </input>  </input>  </ul>  </ul>  </html>  </head>  </link>                                           
March 1, 2018