En Septiembre arrancamos con la séptima edición del Máster Front End Online Lemoncode, es hora de actualizar temario y ver que podemos mejorar, en este post te comentamos las novedades.
Introducción
Hasta hace unos meses, los componentes de clase de React (también llamados stateful components) estaban de moda. Pero eso se acabó con la llegada de los Hooks. ¿Por qué han dejado de ser una buena idea? En este post vamos a enumerar los principales inconvenientes a la hora de trabajar con componentes de clase en React.
La pesadilla del “this”
En componentes de clase, el valor que adopta this dentro de una función dependerá de cómo sea invocada dicha función. Cuando nuestra función es utilizada como manejador de eventos (event handler), el valor al que apunta this será undefined. ¿Por qué? Las declaraciones y expresiones de clase (como por ejemplo nuestra función) se ejecutan en modo estricto, bajo el cual se aplica el binding por defecto a undefined y no a la instancia del componente como cabría esperar.
Más información al respecto aqui: https://medium.freecodecamp.org/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb
Por tanto, el this en un event handler disparado fuera de nuestro componente de clase, perderá la referencia a la instancia a la que pertenece.
Si ejecutamos el siguiente ejemplo y hacemos click en el botón Change Text, obtendremos el error:
Cannot read property ‘setState’ of undefined
export class MyHelloComponent extends React.Component { constructor(props) { super(props); this.state = { myText: "hello" }; } onChangeText() { this.setState({ myText: "world" }); } render() { return ( <> <h3>{this.state.myText}</h3> <button onClick={this.onChangeText}>Change text</button> </> ); } }
La solución pasa por “atar” manualmente el this a la instancia de clase en cada una de las funciones declaradas como métodos de clase. Para ello contamos con dos mecanismos, o bien hacer un binding explícito en el constructor o bien utilizar funciones flecha experimentales (fat arrow) como método de clase (ver linea afectada marcada con el caracter “+”).
export class MyHelloComponent extends React.Component { constructor(props) { super(props); this.state = { myText: "hello" }; + this.onChangeText = this.onChangeText.bind(this); } onChangeText() { this.setState({ myText: "world" }); } render() { return ( <> <h3>{this.state.myText}</h3> <button onClick={this.onChangeText}>Change text</button> </> ); } }
Demo: https://codesandbox.io/s/71opm61rzq
Esta característica de las clases puede llegar a convertirse en una fuente de problemas. ¿Cuántas veces has olvidado hacer adecuadamente el bind a tus event handlers, obteniendo finalmente un error en tiempo de ejecución?
Estado monolítico y funcionalidad difícilmente extraíble
En un componente de clase, tenemos un único lugar donde definir todo el estado al completo, y al mismo tiempo, una única forma de actualizarlo. ¿Inconveniente? Es complicado separar intereses y extraer la funcionalidad para su reuso. Recordemos que la separación de intereses (separation of concerns) y la reutilización de código (code reuse) son dos de los más importantes principios de programación que aparecerán en cualquier manual de buenas prácticas.
En el siguiente ejemplo, tenemos dos conceptos diferentes encapsulados en el mismo estado de clase:
export class MyComponent extends React.Component { constructor(props) { super(props); this.state = { color: "teal", name: "John", lastname: "Doe" }; } getFullname() { return `${this.state.name} ${this.state.lastname}`; } render() { return ( <div style={{ background: this.state.color }}> <h3>{this.getFullname()}</h3> </div> ) } }
Demo: https://codesandbox.io/s/yp9v4yyr8x
Veamos como podríamos implementar el mismo escenario usando hooks. En este caso podremos separar el estado para cada concepto:
import React from "react"; export const MyComponent = () => { const [color, setColor] = React.useState("teal"); const [clientInfo, setClientInfo] = React.useState({name: 'John', lastname: 'Doe'}); const getFullname = () => { return `${clientInfo.name} ${clientInfo.lastname}`; } return ( <div style={{ background: color }}> <h3>{getFullname()}</h3> </div> ); };
Demo: https://codesandbox.io/s/ppom543mj7
Podemos dar un paso más y encapsular la funcionalidad relativa al usuario en un custom hook:
const useClientInfo = (name, lastname) => { const [clientInfo, setClientInfo] = React.useState({ name, lastname, }); const getFullname = () => { return `${clientInfo.name} ${clientInfo.lastname}`; }; return {clientInfo, setClientInfo, getFullname} } export const MyComponent = () => { const [color, setColor] = React.useState("teal"); const {getFullname} = useClientInfo('John', 'Doe'); return ( <div style={{ background: color }}> <h3>{getFullname()}</h3> </div> ); };
Demo: https://codesandbox.io/s/ly7wlq9mo9
Gestión de intereses relacionados en manejadores separados
Cuando usamos componentes de clase en React, disponemos de distintos eventos durante su ciclo de vida en los cuales ejecutar código: componentDidMount, componentDidUpdate, componentWillUnmount, etc. Podría darse el caso de que cierta funcionalidad relacionada tenga que ser dividida entre los distintos handlers del ciclo de vida del componente. Por ejemplo:
Definamos un componente padre:
export class MyComponent extends React.Component { constructor(props) { super(props); this.state = { visible: false }; } render() { return ( <> {this.state.visible && <MyChildComponent />} <button onClick={() => this.setState({ visible: !this.state.visible })}> Toggle Child component visibility </button> </> ); } }
Ahora, un componente hijo que simplemente mostrará la información de usuario:
export class MyChildComponent extends React.Component { constructor(props) { super(props); this.state = { name: "John", lastname: "Doe" }; } componentDidMount() { console.log("Hey Im mounting"); console.log(`${this.state.name} ${this.state.lastname}`); } componentDidUpdate() { console.log("Just updating..."); console.log(`${this.state.name} ${this.state.lastname}`); } componentWillUnmount() { console.log("bye bye, unmounting..."); } render() { return ( <div> <h3> {this.state.name} {this.state.lastname} </h3> <input value={this.state.name} onChange={e => this.setState({ name: e.target.value })} /> <input value={this.state.lastname} onChange={e => this.setState({ lastname: e.target.value })} /> </div> ); } }
Demo: https://codesandbox.io/s/oqyo3159jq
Mediante el empleo de hooks podemos agrupar toda esta funcionalidad en una única función:
const MyChildComponent = () => { const [userInfo, setUserInfo] = React.useState({name: 'John', lastname: 'Doe'}) React.useEffect(() => { console.log('called when the component is mounted and right after it gets updated'); return () => console.log('Clean up from the previous render before running effect next time ... '); }) return ( <div> <h3> {userInfo.name} {userInfo.lastname} </h3> <input value={userInfo.name} onChange={e => setUserInfo({ userInfo, name: e.target.value })} /> <input value={userInfo.lastname} onChange={e => setUserInfo({ userInfo, lastname: e.target.value })} /> </div> ); }
En este ejemplo, el código declarado dentro del useEffect es ejecutado una vez que el componente se ha montado pero también justo después de cada render. Por otro lado, la función de limpieza (devuelta en el useEffect) se ejecuta después de que el componente se haya montado y después de cada ejecución del efecto.
Demo: https://codesandbox.io/s/5zllr3k09p
Bien, pero … ¿y si quiero ejecutar un trozo de código solo cuando el componente se haya montado y hacer la limpieza cuando el componente vaya a desmontarse? Para ello, podemos jugar con el segundo parámetro del useEffect (en el ejemplo marcado con “-” las lineas que se eliminarían, con “+” las líneas que se añaden).
const MyChildComponent = () => { const [userInfo, setUserInfo] = React.useState({name: 'John', lastname: 'Doe'}) React.useEffect(() => { - console.log('called just when the component is mounted and when after it gets updated'); + console.log('called just when the component is mounted'); - return () => console.log('Clean up from the previous render before running effect next time ... '); + return () => console.log('Clean up executed just when the component gets unmounted ... '); - }) + }, []) return ( <div> <h3> {userInfo.name} {userInfo.lastname} </h3> <input value={userInfo.name} onChange={e => setUserInfo({ userInfo, name: e.target.value })} /> <input value={userInfo.lastname} onChange={e => setUserInfo({ userInfo, lastname: e.target.value })} /> </div> ); }
Demo: https://codesandbox.io/s/q91qjql8r4
Ruido al utilizar High Order Components
Un HOC o High Order Component es una excelente forma de añadir nuevas capacidades a tu componente mediante composición, sin embargo:
Necesitas refactorizar su interfaz para poder aplicarlo.
Encadenar diversos HOC simultáneamente puede ser una pesadilla.
Veamos un ejemplo mínimo. El siguiente componente se emplea para saludar al usuario que está actualmente logado:
import React from "react"; export const MyComponent = (props) => { return ( <> <h3>Hello: </h3> </> ) }
Para inyectar el usuario que está actualmente logado podemos crear un HOC:
const withUserInfo = (ComponentToWrap) => (props) => <> <ComponentToWrap {props} user="John" /> </> Let's make usage of this HoC in MyComponent - export const MyComponent = (props) => { + const
Podemos hacer uso de este HOC en MyComponent del siguiente modo:
const MyComponentInner = (props) => { return ( <> <h3>Hello: {props.user}</h3> </> ) } export const MyComponent = withUserInfo()
Demo: https://codesandbox.io/s/l7qznjjyw9
Esta forma de añadir funcionalidad es bastante potente, pero, ¿no sería más sencillo y expresivo un mecanismo con el que podamos decir: “quiero usar esta funcionalidad”? Veamos como implementar este comportamiento utilizando hooks:
import React from "react"; const useUserInfo = () => { const [userInfo, setUserInfo] = React.useState('John'); return {userInfo, setUserInfo} } export const MyComponent = (props) => { const {userInfo} = useUserInfo(); return ( <> <h3>Hello: {userInfo}</h3> </> ) }
Demo: https://codesandbox.io/s/pwj6z446xq
Ventajas:
No necesitamos reescribir el interfaz de nuestro componente: borrar el export, crear un componente para envolverlo, etc.
Sin complicaciones al tener anidando HOCs.
El contrato es claro, no tenemos que adivinar que propiedades está inyectando el HOC a nuestro componente.
Migrando componentes de su forma funcional a clase, y también en el sentido contrario
Cuando iniciamos la implementación de un componente tratamos de mantenerlo sencillo, por lo que es típico comenzar con un componente funcional. Un ejemplo simple podría ser el siguiente: mostrar un mensaje de bienvenida a un usuario (nos lo informa el padre a través de la propiedad userName).
import React from "react"; export const MyComponent = () => { return ( <> <MyChildComponent userName="John"/> </> ) } export const MyChildComponent = (props) => { return ( <> <h3>Hello: {props.userName}</h3> </> ) }
Demo: https://codesandbox.io/s/985wyr1olw
Supongamos que, en lugar de recibirlo desde el padre, queremos almacenarlo en el estado local de nuestro componente. Una aproximación clásica sería migrar nuestro componente a su forma stateful, es decir, refactorizarlo por completo, prestando atención de no equivocarnos con el this.state, añadiendo su constructor, implementando el método render, etc. Algo tal que así:
export const MyComponent = () => { return ( <> <MyChildComponent/> </> ) } export class MyChildComponent extends React.Component { constructor(props) { super(props); this.state = {userName: 'John'} } render() { return ( <> <h3>Hello: {this.state.userName}</h3> </> ) } }
Demo: https://codesandbox.io/s/40l5k4q1o9
¿Cómo podría haber sido este refactor utilizando hooks? Tan sencillo como esto:
export const MyComponent = () => { return ( <> <MyChildComponent/> </> ) } export const MyChildComponent = (props) => { const [userName] = React.useState('John'); return ( <> <h3>Hello: {userName}</h3> </> ) }
Demo: https://codesandbox.io/s/jlkoxm6plw
Combinando componentes funcionales y de clase
Por último, pero no menos importante, en un proyecto de dimensiones considerables, una aproximación mixta donde componentes funcionales y de clase tengan que convivir juntos podría traer diversos inconvenientes de mantenibilidad:
Inconsistencia en nuestra base de código.
Dificultad añadida para que nuevos desarrolladores se inicien en el proyecto, teniendo que aprender ambas formas y decidir cuando es más conveniente una u otra, o cuando deben refactorizar un componente existente en uno u otro sentido.
La refactorización de componentes, ya sea en un sentido u otro, es una tarea propensa a errores, por ejemplo: se nos olvida eliminar el this, nos equivocamos en la sintaxis de clase vs función, errores con la función de render, etc.
Resumiendo
Antes de tirarnos a la piscina con la nueva característica de moda, es importante aprender por qué la necesitamos y que problemas viene a resolver. Esperamos que este artículo pueda ayudaros a entender mejor por qué los hooks han generado tanta expectación en la comunidad y se han convertido en un estándar de facto. En los siguientes artículos de esta serie comenzaremos a indagar en los detalles que hacen a los hooks tan poderosos, mostrando su cara amable y también los casos frontera, basándonos en casos de uso en proyectos reales. ¡Estad atentos!
Esperamos que hayáis disfrutado el artículo. ¡Muchas gracias!
En 2018 presentamos nuestra primera beca Yes We Tech, seleccionamos a dos candidatas para que cursaran el máster , ¿Cual fue el resultado? Tener a dos alumnas muy motivadas, con muchas ganas de trabajar y que como fruto del esfuerzo consiguieron un empleo al finalizar el máster, con estos resultados… ¿ Por qué no repetir? :)
En colaboración con YesWeTech ofrecemos nuestra segunda beca de estudios para aportar nuestro granito de arena a conseguir que haya más diversidad e igualdad de oportunidades en esta profesión. ¿En que consiste? En cubrir el 100% del coste del Máster Front End Online Lemoncode a una alumna que pertenezca a una minoría con baja representación en el sector profesional. Ofrecemos una plaza, y para ello hemos resuelto unas bases para poder inscribiros y seleccionar a la aspirante.
La convocatoría se abre el 15 de Abril y se cierra el 15 de Mayo, el 1 de Junio anunciaremos la persona seleccionada.
A continuación te detallamos las bases de la misma:
Requisitos
Pertenecer a minorías con baja representación en el sector profesional, es decir, mujeres y en especial quienes sean inmigrantes, pertenezcan al colectivo LGTBQIA+, estudiantes y mujeres con con diversidad funcional.
Ingresos inferiores a 27.000€ brutos año o contar con cargas familiaries.
Tener conocimientos previos de programación (sea experiencia laboral, como estudiante, o autodidacta demostrable).
Criterios de evaluación
Horas de estudio semana que la candidata pueda dedicar a la semana.
Curriculum Vitae.
Entrevista personal y opción de realizar prueba técnica a las finalistas.
Información mínima a enviar
Documento personal identificativo (DNI, NIE, Pasaporte)
Carta explicando los motivos por los que la alumna está interesada en realizar el máster.
Número de horas de estudio semanal que le puede dedicar al máster
Curriculum Vitae.
Información salarial (no es necesario el envío de documentación acreditativa, pero se podría requerir si la candidata llega a finalista).
Fechas
Aceptación candidatas del 15 de Abril al 15 de Mayo de 2019.
Fecha resolución beca (1 plaza) 1 de Junio de 2019.
Fecha arranque Máster 22 de Septiembre de 2019
Comite evaluador
Miembros de la comunidad YesWeTech.
Miembros de Lemoncode Formacion S.L.
Para aplicar envíanos un correo con la información que te pedimos a nuestra cuenta de EMail: formacion@lemoncode.net
Te estamos muy agradecidos si nos ayudas a difundir esta beca.
A lo largo de las 5 ediciones de este Máster hemos tenido la suerte de contar con un buen número de estudiantes y nos han planteado cuestiones muy interesantes que nos gustaría compartir. En este post te resumimos las más comunes (si tienes alguna consulta que no este recogida en este artículo no dudes en contactar con nosotros). Espero que te sea de utilidad.
En Marzo arrancamos con la sexta edición del Máster Front End Online Lemoncode, como en cada edición, nos hemos evaludo como evoluciona el mercado, y el feedback de los estudiantes y nos hemos puesto manos a la obra.
Introducción
Este post está basado en este excelente Gist de Carlos Hidalgo
Cuando trabajamos con imports, una de las cosas que más duelen (y huelen) es trabajar con rutas relativas, es decir, si tenemos una estructura como esta:
Y por ejemplos estamos editando el fichero pods/movies/movies-grid.container.ts Y queremos desde nuestra página referenciar a un elemento de la carpeta api, tendríamos que hacer un import del tipo:
import {fetchMovies} from '../../api';
Con uno o dos niveles “../” igual esto no tiene mala pinta, pero a veces te puedes encontrar con cosas como:
import { TrainingSummary } from '../../../../model/trainingSummary';
Y lo que es peor, si refactorizamos y movemos de carpetas ficheros acabamos teniendo un lio de imports.
¿ Que solución podemos aplicar? crear unos alias a nivel de carpeta principal, que nos permitan minimizar el uso de carpetas relativas, es decir en este caso si hago un alias a la carpeta api, el import relativo que creamos anteriormente se quedaría de la siguiente manera:
import {fetchMovies} from '/api';
La idea aquí es crear unos alias en carpetas de primer nivel y evitar el infierno de rutas relativas.
Y..¿ Esto es fácil de configurar? Bueno más que fácil, tiene truco, tienes que saber bien donde tocar:
Hay que indicarle a webpack los mappings de esos alias (tocaremos el webpack.config.js).
Hay que ayudar a VSCode y Typescript a mapear esos alias (tocaremos el tsconfig.json).
Y si tenemos pruebas unitarias con JEST también debemos de indicarle los mapeos de carpeta a alias (aquí actualizaremos el fichero de configuración de jest, sea el jest.json o el propio package.json, depende de donde tengamos la configuración).
Con la hoja de ruta que os vamos a definir, a partir de ahora configurar un grupo de alias va a ser pan comido :).
Configurando webpack
Webpack necesita saber a paths físicos mapean los alias, abrimos el fichero webpack.config.js y añadimos a la sección resolve, una subsección que llamaremos alias y ahí listamos todos los mapeos de alias a ruta, quedaría tal que así:
webpack.config.json
module.exports = { resolve: { alias: { api: path.resolve(__dirname, './src/api/'), commonApp: path.resolve(__dirname, './src/common-app/'), core: path.resolve(__dirname, './src/core/'), layout: path.resolve(__dirname, './src/layout/'), pods: path.resolve(__dirname, './src/pods/'), scenes: path.resolve(__dirname, './src/scenes/'), }, extensions: ['.js', '.jsx', '.ts', '.tsx'], },
Configurando Typescript + Visual Studio code
Ahora nos toca que Typescript y Visual Studio Code se lleven bien con estos alias, para ellos en el tsconfig, tenemos que decirle cual es nuestra carpeta de partida (en este caso la src) y crear una sección de paths en la que añadimos nuestra lista de alias (muy importante: esta lista de paths tiene que ir debajo de la sección de compilerOptions).
tsconfig.json
{ "compilerOptions": { "moduleResolution": "node", "baseUrl": "./src/", "paths": { "api": ["./api/*"], "common-app": ["./common-app/*"], "core": ["./core/*"], "layout": ["./layout/*"], "pods": ["./pods/*"], "scenes": ["./scenes/*"] } } }
Configurando Jest
Cómo último paso, si estamos usando Jest, tenemos que añadir la lista de paths al fichero de configuración, dependiendo del proyecto la configuracíon de jest te la puedes encontrar en el mismo package.json o en un fichero específico (jest.json o similar), en el ejemplo que cubrimos se encuentra en el jest.json.
/config/jest.json
{ "moduleNameMapper": { "^api/(.*)$": "/src/api/$1", "^common-app/(.*)$": "/src/common-app/$1", "^core/(.*)$": "/src/core/$1", "^layout/(.*)$": "/src/layout/$1", "^pods/(.*)$": "/src/pods/$1", "^scenes/(.*)$": "/src/scenes/$1" } }
Ejemplo real
Si quieres ver esto aplicado en un proyecto real, aquí tienes:
La pull request con los cambios paso a paso: https://github.com/Lemoncode/movies-pods/pull/55/files
El proyecto en el que lo hemos implementado: https://github.com/Lemoncode/movies-pods
Agradecimientos
Este post está basado en este excelente Gist de Carlos Hidalgo, que se pego unas horas de investigación y cabezazos hasta que dio con los pasos exactos :).
¿Con ganas de aprender desarrollo Front End?
Si tienes ganas de ponerte al día en el mundo del Front End, impartimos un máster online con clases en vivo. Para más información: http://lemoncode.net/master-frontend
En el Máster Front End Online Lemoncode, participamos un equipo de 12 de profesores, y también una serie de empresas que están adheridas a nuestra bolsa de trabajo. ¿Alguna vez te ha picado la curiosidad de saber de donde venimos o qué hacemos? Continuamos esta de serie de posts entrevistando a Juan José Montiel, profesor del máster Front End Online Lemoncode, experto en accesibilidad y Microsoft MVP.
En el Máster Front End Online Lemoncode, participamos un equipo de 12 de profesores, y tambíen una serie de empresas que están adheridas a nuestra bolsa de trabajo. ¿Alguna vez te ha picado la curiosidad de saber de donde venimos o qué hacemos? Abrimos sería de posts con entrevistas al equipo y empresas que colaboradon en este máster.
Empezamos entrevistando a Erik Rasmussen, el desarrollador de proyectos tales como Redux-Forms, o guías como Redux Ducks
En esta ocasión entrevista Javier García Magna, Head of Development and Testing Practices de Sequel en Málaga (empresa adherida a nuestra bolsa de trabajo).
En el post anterior vimos en que consistía el "Server Side Rendering" a nivel de teoría y conceptos, en este segundo post de la serie vamos a pasar a fase de implementación, para ello hemos elegido como tecnología React y como framework de server side rendering Nextjs.
Ya estamos en la quinta edición del Máster Front End Online. Como cada año, toca revisar temario y añadir actualizaciones y mejoras.
Esta serie de dos posts viene inspirada por la charla que impartimos en el Open South Code 2018 sobre la integración entre React y D3.js, cuyo material puedes encontrar aqui: fjcalzado.surge.sh. En esta primera parte haremos un breve repaso de ambas librerías, centrándonos principalmente en la gestión del DOM. Veremos conceptos interesantes y concluiremos con la problemática a la hora de trabajar con ambos frameworks. En la segunda parte, explicaremos las distintas soluciones disponibles y las ilustraremos con código y ejemplos. ¡Vamos allá!
El otro día en el Máster Front End Lemoncoders, Eirik Rasmussen nos dió una sesión muy interesante sobre server side rendering y como implementarlo usando React y Next. Eso nos ha animado a escribir una serie de posts en la que explicamos como funciona esto de manera detallada.
En este primer artículo de la serie vamos a centrarnos en es explicar bien el problema que viene a resolver "Server side rendering" así como conceptos de base, en siguientes entrega nos meteremos de lleno en una implementación utilizando Next y React.
En la entrega anterior vimos como podíamos usar webpack-bundle-analyzer para ver que librerías de terceros hacían que nuestro "bundle" estuviera gordo.
En esta entrega vamos a ver como habilitar treeshaking en esas librerías y reducir su tamaño de forma considerable. Como ejemplo trabajaremos con una librería de componentes popular: material_ui, crearemos un aplicacíon simple y veremos como reducimos el espacio que ocupa esta librería en nuestra aplicación, pasaremos de un peso de 960 Kb a 56 Kb.
Abrimos una serie de posts en lo que nos centramos en aligerar el peso de nuestros bundles, en este primer post os presentamos una herramienta que os ayudará a identificar que paquetes son culpables del "sobrepeso" de tu aplicación.
Hace unos meses ofrecimos un descuentazo para el curso de .net core, ahora le toca al de nodejs, es hora de ponerte al día con la grabación del curso “Creación de API’s REST con nodejs, express, mongoose, mongo” de 21 horas de duración.
El temario del curso:
- Comenzar con node
- Modulos
- Modelo asíncrono
- Eventos.
- Streams.
- Sistema local.
- Aproximacion Web.
- Mongo.
- Mongoose.
- Rest Api con Express.
¿Qué tal está este curso?
Te pasamos la opinión de un alumno (Jorge Carballo):
"Esta formación me encanto. Había estado tocando algo de nodejs y con el curso he aprendido mucho y he descubierto que es una tecnología muy interesante. Me ha dado pie a investigar y practicar más sobre nodejs."
Hemos publicado una oferta especial limitada a los primeros 50 primeros que adquiráis este curso. El precio normal es de 150 €, presentando el cupón que te adjuntamos, esté te saldría por 45 €.
Instrucciones para canjear este cupón:
- Date de alta en la plataforma: https://campus.lemoncode.net/courses/introducci-n-a-node-js-orientado-a-rest-api
Pincha en comprar el curso de nodejs.
Regístrate como usuario (te puedes registrar también con linkedin).
En el proceso de compra antes de meter tu tarjeta de crédito, mira en la parte superior izquierda encontrarás un enlace para introducir un cupón de descuento.
- Mete este cupón:
nodejsnewsletter34hnc3 - Con eso ya te sale el curso por sólo 45 € y ya puedes introducir tu tarjeta de crédito para realizar el pago.
Hace unos días que publicamos una oferta para los subscriptores de nuestra newsletter, la grabación de un curso bien completo de .net core (21 horas de duración), impartido por nada más y nada menos que Eduard Tomás (MVP ASP .net), con un 70% de descuento (el curso tiene un coste de 150 €, con el cupón se te quedaría en 45 €).
Está oferta ha tenido una muy buena acogida, hemos decidido abrirla a la comunidad a los 50 primeros que adquieran el curso.
¿ Qué tal está el curso? Te pasamos la opinión de un alumno que lo cursó
"En este curso de .NET Core 2.0 de los chicos de Lemoncode, el maestro en la materia Eduard Tomás da un repaso magnifico de la tecnología y no contento con ello, nos aporta como añadido conocimientos de C#, inyección de dependencias, entity framework core, métodos de extensión, etc.
Sin conocer .NET Core me ha aportado muchísimo y he salido con ganas de más.
Eduard es un gran conocedor de la materia, muy didáctico y comunicador lo que hace una combinación perfecta para sumergirte en la materia.
Recomendado 100%."
Antonio Tobajas (Alumno curso .net core)
¿ Qué temario tiene? Lo puedes consultar en este enlace: https://lemoncode.net/creacion-de-rest-apis-con-net-core
¿ Tienes fecha límite para verlo? No, lo puedes ver cuando y cuantas veces quieras, es más te puedes bajar el contenido a tu disco duro.
Instrucciones para obtener el descuento:
- Date de alta en la plataforma: https://campus.lemoncode.net/courses/creaci-n-de-apis-rest-con-net-core
- Pincha en comprar el curso de .net core.
- En el proceso de compra antes de meter tu tarjeta de crédito, mira en la parte superior izquierda encontrarás un enlace para introducir un cupón de descuento.
- Mete este cupón:
netcorenewsletter89hp765
- Con este cupón te sale el curso por sólo 45 € y ya puedes introducir tu tarjeta de crédito para realizar el pago.
Ya tenemos la resolución de la beca Yes We Tech. Lo primero pediros disculpas por el retraso en resolverla, la fecha oficial era el 5 de Febrero, nos hemos retrasado unos días, porque hemos recibido un buen número de solicitudes muy interesantes y nos ha costado mucho decidirnos... tanto que hemos ampliado el número de plazas becadas de una a dos.
La asincronía es uno de los pilares fundamentales de Javascript. ¿Nunca has llegado a entender en profundidad como funciona? ¿Crees que es magia lo que sucede al utilizar promesas? Entra en esta guía definitiva y aprende de una vez por todas como funciona la asincronía en Javascript. Su comprensión mejorará en gran medida tu código y te ayudará a escribir mejores aplicaciones.