Platzi
Platzi

¡Invierte en ti y celebremos! Adquiere un plan Expert o Expert+ a precio especial.

Antes: $349
$259
Currency
Antes: $349
Ahorras: $90
COMIENZA AHORA
Termina en: 7D : 1H : 13M : 10S

Debes iniciar sesión

Para ver esta clase crea una cuenta sin costo o inicia sesión

Curso de React Router y Redux

Curso de React Router y Redux

Oscar Barajas Tavares

Oscar Barajas Tavares

Container: Login

4/29

Vamos a descargar el proyecto del curso de Frontend de escuela de JavaScript para crear los componentes que necesitaremos, en caso de que vengas del curso de React no debes descargar nada.

Debemos modificar nuestra configuración del entorno de desarrollo local para que pueda funcionar con el uso de rutas, debemos ir al archivo webpack.config.js y añadir este fragmento de código antes de plugins:

module.exports = {
  {/*...*/}
  devServer: {  
    historyApiFallback: true,  
  },
  {/*...*/}
}

Aqui esta el codigo de section para quien lo necesite

<section className='login'>
		<section className='login__container'>
			<h2>Inicia sesión</h2>
			<form className='login__container--form'>
				<input className='input' type='text' placeholder='Correo' />
				<input className='input' type='password' placeholder='Contraseña' />
				<button className='button'>Iniciar sesión</button>
				<div className='login__container--remember-me'>
					<label>
						<input type='checkbox' id='cbox1' value='first_checkbox' />
						Recuérdame
					</label>
					<a href='/'>Olvidé mi contraseña</a>
				</div>
			</form>
			<section className='login__container--social-media'>
				<div>
					<img src='../assets/google-icon.png' /> Inicia sesión con Google
				</div>
				<div>
					<img src='../assets/twitter-icon.png' /> Inicia sesión con Twitter
				</div>
			</section>
			<p className='login__container--register'>
				No tienes ninguna cuenta <a href=''>Regístrate</a>
			</p>
		</section>
	</section>```

les comparto el css de este video + algunos detallitos faltantes.

.login {
  background-image: linear-gradient(#21c08b, #8f57fd);
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  padding: 0px 30px;
  min-height: calc(100vh - 200px); /* El ancho será igual al tamaño de todo el height menos 200px (100px del header + 100px del footer) */
}

.login__container {
  background-color: rgba(255,255,255,0.1);
  border: 2px solid white;
  border-radius: 40px;
  box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
  color: white;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  min-height: 700px;
  padding: 60px 60px 40px;
  width: calc(100% / 2);
}

.login__container--form {
  display: flex;
  flex-direction: column;
}

.login__container--form label {
  font-size: 14px;
}

.login__container--remember-me {
  color: white;
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
}

.login__container--remember-me a {
  color: white;
  font-size: 14px;
  text-decoration: none;
}

.login__container--remember-me a:hover {
  text-decoration: underline;
}

.login__container--social-media > div {
  align-items: center;
  display: flex;
  font-size: 14px;
  margin-bottom: 10px;
}

.login__container--social-media > div > img {
  margin-right: 10px;
  width: 30px;
}

.login__container--register {
  font-size: 14px;
}

.login__container--register a {
  color: white;
  font-weight: bold;
  font-size: 16px;
  text-decoration: none;
}

.login__container--register a:hover {
  text-decoration: underline;
}

.login__container--form > .input {
  background-color: transparent;
  border-bottom: 2px solid white;
  border-left: 0px;
  border-right: 0px;
  border-top: 0px;
  color: white;
  font-family: 'Muli', sans-serif;
  font-size: 16px;
  height: 50px;
  margin-bottom: 20px;
  outline: none;
  padding: 0px 20px;
  min-width: 100%;
}

::placeholder {
  color: white;
}

.button {
  background-color: rgba(255, 255, 255, 0.3);
  border: none;
  border-radius: 25px;
  color: white;
  cursor: pointer;
  font-size: 16px;
  font-weight: bold;
  font-family: 'Muli', sans-serif;
  height: 50px;
  letter-spacing: 1px;
  margin: 10px 0px;
}



Para no tener que abrir otro tab u otra ventana de la terminal solo para levantar el “json-server”, modifica los scripts de tu package.json de esta manera:

    "server": "json-server initialState.json",
    "start": "webpack-dev-server --open --mode development & npm 	 
    run server"

Así, al ejecutar npm start se levantará tanto el servidor de desarrollo como el json-server

Muy dinamicas tus clases. Y es admirable la facilidad para explicar las cosas sin mucho enredo.

Un poco de documentacion para entender un poco devServer: Click Aqui

Les comparto el código css convertido a sass:

Login.scss

.login {
	background-image: linear-gradient(#21c08b, #8f57fd);
	display: flex;
	align-items: center;
	flex-direction: column;
	justify-content: center;
	padding: 0px 30px;
  min-height: calc(100vh - 200px);

  &__container {
    background-color: rgba(255,255,255,0.1);
    border: 2px solid white;
    border-radius: 40px;
    box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
    color: white;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    min-height: 700px;
    padding: 60px 68px 40px;
    width: 300px;

    &--form {
      display: flex;
      flex-direction: column;
      label {
        font-size: 14px;
      }
    }

    &--remember-me {
      color: white;
      display: flex;
      justify-content: space-between;
      margin-top: 10px;
      a {
        color: white;
        font-size: 14px;
        text-decoration: none;
        &:hover {
          text-decoration: underline;
        }
      }
    }

    &--social-media {
      >div {
        align-items: center;
        display: flex;
        font-size: 14px;
        margin-bottom: 10px;
        >img {
          margin-right: 10px;
          width: 30px;
        }
      }
    }

    &--register {
      font-size: 14px;
      a {
        color: white;
        font-weight: bold;
        font-size: 16px;
        text-decoration: none;
        &:hover {
          text-decoration: underline;
        }
      }
    }

  }
}

Para abrir una sola terminal y correr el json-server y nuestro proyecto podemos instalar el paquete concurrently: npm install concurrently --save-dev
Y después agregamos estos scripts en el archivo package.json en la zona de scripts:
“server”: “json-server initialState.json”,
“dev”: “webpack-dev-server --open --mode development”,
“start”: “concurrently “npm run server” “npm run dev””,
de este modo al dar npm run start se abren el json-server y nuestro proyecto desde una sola terminal.

Container: Login

Creamos el componente para el Login; lo hacemos en los contenedores como componente presentacional; usamos las imágenes; creamos los estilos.

Importamos nuestro componentes a nuestro archivo de rutas; lo añadimos a una ruta.

<Rute exact path="/login" component={Login} />

Antes de plugins en el archivo de configuración de webpack debemos colocar lo siguiente para trabajar con rutas e historias en el navegador.

devServer: {
    historyApiFallback:true,
}
Captura de pantalla de 2020-05-02 21-32-10.png

Esa configuración de web pack solo aplica en desarrollo, ¿Pero en producción ya no es necesario agregar algo mas?

Que tal, para aquellos que tengan errores con el archivo de eslint que se dio en el curso de React Practico, lo estuve revisando y solvente todos los errores, aqui les dejo el link del gist que hice: https://gist.github.com/matias4205/e623b25c1f3c3859a072d9a98d8c1b10

Come se relaciona esto con el back end. O ya utilizando estas herramientas estamos reemplazando el back end

En Vscode existe una extensión llamada.

html to jsx

Muy buena para estos casos en los que estas pasando contenido de HTML a JSX!!

De esta forma carga automáticamente la App después del npm run start.

  devServer: {
    open: true,
    hot: true,
    port: 8081,
    historyApiFallback: true,
  },

Oscar hay que trabajar en pedagogía.

Se puede tener conocimiento de algún tema y para saberlo transmitir hay que aplicar pedagogía y una buena estructura de planeación de lo que se va a enseñar,

Muchos cursos de Platzi fallan en este punto.

Mi diseño se estaba viendo así:Captura de pantalla (355).png
y lo resolví solo eliminando una línea de Css
Captura de pantalla (354).png

.login__container{
    background-color: rgba(255, 255, 255, 0.1);
    border: 2px solid white;
    border-radius: 40px;
    color: white;
    padding: 60px 68px 40px;
    // width: 300px; //Esta línea
    min-height: 700px;
    display: flex;
    justify-content: space-around;
    flex-direction: column;
}

Como hacer para que salga el emoji a mi tambien??

Muy buena clase.

IMAGE 2020-08-12 18:44:22.jpg
const app = () => (
    <BrowserRouter>
        <Route exact path="/" component={Home} />
        <Route exact path="/login" component={Login} />
    </BrowserRouter>
);

Tengo la misma configuración de Eslint y me aparecen muchos “errores” que al profe no le aparece, lo mismo me pasaba en el curso pasado ): Más allá del origen de lo que produce el error mi pregunta es porqué a mi me aparecen y al profe no teniendo exactamente el mismo .eslintrc, mi node corre sobre WSL (Ubuntu), últimas versiones de todo

Pregunta.
Me ha salido el siguiente error y no se como solucionarlo Captura de Pantalla 2020-04-13 a la(s) 10.56.40.png
Ya llevo dos días y no puedo pasar de este tema, me he regresado y he visto el siguiente y sigo con el mismo error. alguien que me pueda ayudar por favor.

Adjunto mi repositorio : https://github.com/SoterRamirez/EducVideo/tree/feature/router-redux
Desde ya, muchas gracias por su ayuda.

Yo estoy practicando, uso un archivo webpack.config.dev.js y esta solucion del profe no me funciono, lei la documentacion y encontre que escribiendo lo siguiente en el archivo webpack.config.dev.js funciona perfectamente.

  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    stats: 'errors-only',
    open: true,
    port: 3006,
    compress: true,
    historyApiFallback: true,
  },

les comparto el codigo de esta clase
Login.jsx

import React from "react";
import "../assets/styles/components/Login.scss";
import googleIcon from "../assets/static/google-icon.png";
import twitterIcon from "../assets/static/twitter-icon.png";

const Login = () => {
	return (
		<section className="login">
			<section className="login__container">
				<h2>Inicia sesión</h2>
				<form className="login__container--form">
					<input className="input" type="text" placeholder="Correo" />
					<input className="input" type="password" placeholder="Contraseña" />
					<button className="button">Iniciar sesión</button>
					<div className="login__container--remember-me">
						<label>
							<input type="checkbox" id="cbox1" value="first_checkbox" />
							Recuérdame
						</label>
						<a href="/">Olvidé mi contraseña</a>
					</div>
				</form>
				<section className="login__container--social-media">
					<div>
						<img src={googleIcon} /> Inicia sesión con Google
					</div>
					<div>
						<img src={twitterIcon} /> Inicia sesión con Twitter
					</div>
				</section>
				<p className="login__container--register">
					No tienes ninguna cuenta <a href="">Regístrate</a>
				</p>
			</section>
		</section>
	);
};

export default Login;

Login.scss

.login {
	background-image: linear-gradient(#21c08b, #8f57fd);
	display: flex;
	align-items: center;
	flex-direction: column;
	justify-content: center;
	padding: 0px 30px;
	min-height: calc(
		100vh - 200px
	); /* El ancho será igual al tamaño de todo el height menos 200px (100px del header + 100px del footer) */
}

.login__container {
	background-color: rgba(255, 255, 255, 0.1);
	border: 2px solid white;
	border-radius: 40px;
	box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
	color: white;
	display: flex;
	flex-direction: column;
	justify-content: space-around;
	min-height: 700px;
	padding: 60px 68px 40px;
	width: 300px;
}

.login__container--form {
	display: flex;
	flex-direction: column;
}

.login__container--form label {
	font-size: 14px;
}

.login__container--remember-me {
	color: white;
	display: flex;
	justify-content: space-between;
	margin-top: 10px;
}

.login__container--remember-me a {
	color: white;
	font-size: 14px;
	text-decoration: none;
}

.login__container--remember-me a:hover {
	text-decoration: underline;
}

.login__container--social-media > div {
	align-items: center;
	display: flex;
	font-size: 14px;
	margin-bottom: 10px;
}

.login__container--social-media > div > img {
	margin-right: 10px;
	width: 30px;
}

.login__container--register {
	font-size: 14px;
}

.login__container--register a {
	color: white;
	font-weight: bold;
	font-size: 16px;
	text-decoration: none;
}

.login__container--register a:hover {
	text-decoration: underline;
}

routes/App.js

import React from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Home from "../containers/Home";
import Login from "../containers/Login";
const App = () => {
	return (
		<BrowserRouter>
			<Route exact path="/" component={Home} />
			<Route exact path="/login" component={Login} />
		</BrowserRouter>
	);
};

export default App;

webpack.config.js

const path = require("path");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
	entry: "./src/index.js",
	output: {
		path: path.resolve(__dirname, "dist"),
		filename: "bundle.js",
	},
	resolve: {
		extensions: [".js", ".jsx"],
	},
	module: {
		rules: [
			{
				test: /\.(js|jsx)$/,
				exclude: /node_modules/,
				use: {
					loader: "babel-loader",
				},
			},
			{
				test: /\.html$/,
				use: [
					{
						loader: "html-loader",
					},
				],
			},
			{
				test: /\.(s*)css$/,
				use: [
					{
						loader: MiniCssExtractPlugin.loader,
					},
					"css-loader",
					"sass-loader",
				],
			},
			{
				test: /\.(png|gif|jpg)$/,
				use: [
					{
						loader: "file-loader",
						options: {
							name: "assets/[hash].[ext]",
						},
					},
				],
			},
		],
	},
	devServer: {
		historyApiFallback: true,
	},
	plugins: [
		new HtmlWebPackPlugin({
			template: "./public/index.html",
			filename: "./index.html",
		}),
		new MiniCssExtractPlugin({
			filename: "assets/[name].css",
		}),
	],
};

Buenas, que debo hacer para solucionar el error con los archivos .json

Uncaught Error: Cannot find module './translationses.json'
    at webpackContextResolve (.json$:13)
    at webpackContext (.json$:8)
    at App (App.js:14)
    at renderWithHooks (react-dom.development.js:14803)
    at mountIndeterminateComponent (react-dom.development.js:17482)
    at beginWork (react-dom.development.js:18596)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at beginWork$1 (react-dom.development.js:23203)

gracias…

Me encanta la seguidilla de cursos pero todavía no entiendo para que dedicarle tanto tiempo a la configuración manual del webpack

El historyApiFallback: true de React Router es un simil de mode: ‘history’, en Vuejs. ? o cumplen finalidades distintas

Los primeros pasos con Router, buenisimo!

woooo, excelente clase 😄

Sigo sin poder hacer match con login

que bueno es volver a ver el curso y en practica mucho mejor

Vengo del curso Practico de React, con mi proyecto de Platzi video sin errores ejecutándose correctamente.
Tengo todo correcto en código fuente no hay errores sin embargo al ejecutar
npm run start

react.development.js:167 Warning: React.createElement: type is invalid – expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.
Check the render method of App.
in App

Aparece el error descrito arriba, ya revise todo estoy haciendo bien las exportaciones
Investigando aplique la solución que aparece en esta URL
https://platzi.com/clases/1079-react-2016/6326-actualizando-a-la-ultima-version-de-react-router/
luego ejecuto nuevamente npm run start y me pedia instalar react-router
npm install --save react-router
pero al final regresa al mismo error
Check the render method of App.
in App

He aquí la documentación del api de DevServer historyApiFallback

Buena clase.

hola…me aparece esta advertencia:

Advertencia internal-error (ESLint) Failed to load config “prettier” to extend from.

¿Alguna idea de porqué será?

WhatsApp Image 2020-04-19 at 12.31.39 PM.png

Listo me toé con varios errores pero quedo todo bien hasta esta parte

me surge una duda. ¿Hay algun problema si se deja el Archivo App con extension JSX?

Debemos modificar nuestra configuración del entorno de desarrollo local para que pueda funcionar con el uso de rutas, debemos ir al archivo webpack.config.js y añadir este fragmento de código antes de plugins:

module.exports = {
{//}
devServer: {
historyApiFallback: true,
},
{//}
}

Alguien sabe por que cuando corro la aplicacion, se renderizan las dos rutas en la misma pantalla Captura de pantalla de 2020-06-24 17-26-10.png

Que buena explicación por parte de Oscar.

Hola Todos, este es mi código!!!







No me gusta que va copiando codigo, esa no es la idea de un curso.

Muy buena clase.

IMAGE 2020-08-11 20:34:29.jpg

Al agregar la configuración del devServer me sale el siguiente error
errorDevServer.png

Otra solución para correr el servidor jason sin usar otra consola u otro tab es instalar la dependencia npm-run-all y modificar lo siguiente en tu archivo jason:

"client": "webpack-dev-server --open --mode development",
 "server": "json-server --port 3001 --watch initialState.json",
 "start": "npm-run-all -p client server",

Cuando manejamos nuestro entorno de desarrollo local, debemos hacer que pueda manejar las rutas. Hacemos esto en el archivo de webpack.config.js

devServer: {
    historyApiFallback: true,
  }

import de las imagenes

import googleIcon from "../assets/static/google-icon.png"
import twitterIcon from "../assets/static/twitter-icon.png"

Pueden utilizar este convertidor de HTML a JSX si su editor les marca error

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <!-- Font -->
  <link href="https://fonts.googleapis.com/css?family=Muli&display=swap" rel="stylesheet">
  <!-- Styles -->
  <link rel="stylesheet" href="./styles.css">
  <!-- Title -->
  <title>Inicia Sesión</title>
</head>
<body>
  <header class="header">
    <img class="header__img" src="../assets/logo-platzi-video-BW2.png" alt="Platzi Video">
  </header>
  <section class="login">
    <section class="login__container">
      <h2>Inicia sesión</h2>
      <form class="login__container--form">
        <input class="input" type="text" placeholder="Correo">
        <input class="input" type="password" placeholder="Contraseña">
        <button class="button">Iniciar sesión</button>
        <div class="login__container--remember-me">
          <label>
            <input type="checkbox" id="cbox1" value="first_checkbox">Recuérdame
          </label>
          <a href="/">Olvidé mi contraseña</a>
        </div>
      </form>
      <section class="login__container--social-media">
        <div><img src="../assets/google-icon.png"> Inicia sesión con Google</div>
        <div><img src="../assets/twitter-icon.png"> Inicia sesión con Twitter</div>
      </section>
      <p class="login__container--register">No tienes ninguna cuenta <a href="">Regístrate</a></p>
    </section>
  </section>
  <footer class="footer">
    <a href="/">Terminos de uso</a>
    <a href="/">Declaración de privacidad</a>
    <a href="/">Centro de ayuda</a>
  </footer>
</body>
</html>```

Me estaba saliendo este error. err.PNG

Luego de ver dos veces el video, me di cuenta que al definir la constante Login en Login.jsx todo es con paréntesis y yo lo había hecho con llaves lo que abarca la “section”. Ahora todo OK. 😉

Así es como tengo a Login.jsx

import React from 'react';
import googleIcon from '../assets/static/google-icon.png';
import twitterIcon from '../assets/static/twitter-icon.png';
import '../assets/styles/components/Login.scss';

const Login = () => (
<section className='login'>
    <section className='login__container'>
      <h2>Inicia sesión</h2>
      <form className='login__container--form'>
        <input className='input' type='text' placeholder='Correo' />
        <input className='input' type='password' placeholder='Contraseña' />
        <button className='button'>Iniciar sesión</button>
        <div className='login__container--remember-me'>
          <label>
            <input type='checkbox' id='cbox1' value='first_checkbox' />
            Recuérdame
          </label>
          <a href='/'>
            Olvidé mi contraseña
          </a>
        </div>
      </form>
      <section className='login__container--social-media'>
        <div><img src={googleIcon} /> Inicia sesión con Google</div>
        <div><img src={twitterIcon} /> Inicia sesión con Twitter</div>
      </section>
      <p className='login__container--register'>No tienes ninguna cuenta <a href=''>Regístrate</a></p>
    </section>
</section>
);
export default Login;

import React from "react";

const Login = () => {
  return (
    <section className="login">
      <section className="login__container">
        <h2>Inicia sesión</h2>
        <form className="login__container--form">
          <input className="input" type="text" placeholder="Correo" />
          <input className="input" type="password" placeholder="Contraseña" />
          <button className="button">Iniciar sesión</button>
          <div className="login__container--remember-me">
            <label>
              <input type="checkbox" id="cbox1" value="first_checkbox" />
              Recuérdame
            </label>
            <a href="/">Olvidé mi contraseña</a>
          </div>
        </form>
        <section className="login__container--social-media">
          <div>
            <img src="../assets/google-icon.png" /> Inicia sesión con Google
          </div>
          <div>
            <img src="../assets/twitter-icon.png" /> Inicia sesión con Twitter
          </div>
        </section>
        <p className="login__container--register">
          No tienes ninguna cuenta <a href="">Regístrate</a>
        </p>
      </section>
    </section>
  );
};
export default Login;

.

El componente es similar a un elemento ya que nos permite navegar dentro de la aplicación, pero sin necesidad de recargar la página. Para indicar el destino, simplemente pasamos el prop a = ‘/ my-link’.

Primero importe el enlace desde react-router-dom. Agregue la etiqueta de enlace a la etiqueta de anclajes de la imagen del logotipo, también con la cuenta y la sección de cierre.

Además, necesitamos implementar el componente Link en nuestro contenedor de inicio de sesión.

![](l1png.png

Genial!

Para entender por qué se coloca historyApiFallback en el webpack

Práctica:
2.PNG

Aqui esta el codigo de section para quien lo necesite

<section className='login'>
		<section className='login__container'>
			<h2>Inicia sesión</h2>
			<form className='login__container--form'>
				<input className='input' type='text' placeholder='Correo' />
				<input className='input' type='password' placeholder='Contraseña' />
				<button className='button'>Iniciar sesión</button>
				<div className='login__container--remember-me'>
					<label>
						<input type='checkbox' id='cbox1' value='first_checkbox' />
						Recuérdame
					</label>
					<a href='/'>Olvidé mi contraseña</a>
				</div>
			</form>
			<section className='login__container--social-media'>
				<div>
					<img src='../assets/google-icon.png' /> Inicia sesión con Google
				</div>
				<div>
					<img src='../assets/twitter-icon.png' /> Inicia sesión con Twitter
				</div>
			</section>
			<p className='login__container--register'>
				No tienes ninguna cuenta <a href=''>Regístrate</a>
			</p>
		</section>
	</section>```

les comparto el css de este video + algunos detallitos faltantes.

.login {
  background-image: linear-gradient(#21c08b, #8f57fd);
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  padding: 0px 30px;
  min-height: calc(100vh - 200px); /* El ancho será igual al tamaño de todo el height menos 200px (100px del header + 100px del footer) */
}

.login__container {
  background-color: rgba(255,255,255,0.1);
  border: 2px solid white;
  border-radius: 40px;
  box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
  color: white;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  min-height: 700px;
  padding: 60px 60px 40px;
  width: calc(100% / 2);
}

.login__container--form {
  display: flex;
  flex-direction: column;
}

.login__container--form label {
  font-size: 14px;
}

.login__container--remember-me {
  color: white;
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
}

.login__container--remember-me a {
  color: white;
  font-size: 14px;
  text-decoration: none;
}

.login__container--remember-me a:hover {
  text-decoration: underline;
}

.login__container--social-media > div {
  align-items: center;
  display: flex;
  font-size: 14px;
  margin-bottom: 10px;
}

.login__container--social-media > div > img {
  margin-right: 10px;
  width: 30px;
}

.login__container--register {
  font-size: 14px;
}

.login__container--register a {
  color: white;
  font-weight: bold;
  font-size: 16px;
  text-decoration: none;
}

.login__container--register a:hover {
  text-decoration: underline;
}

.login__container--form > .input {
  background-color: transparent;
  border-bottom: 2px solid white;
  border-left: 0px;
  border-right: 0px;
  border-top: 0px;
  color: white;
  font-family: 'Muli', sans-serif;
  font-size: 16px;
  height: 50px;
  margin-bottom: 20px;
  outline: none;
  padding: 0px 20px;
  min-width: 100%;
}

::placeholder {
  color: white;
}

.button {
  background-color: rgba(255, 255, 255, 0.3);
  border: none;
  border-radius: 25px;
  color: white;
  cursor: pointer;
  font-size: 16px;
  font-weight: bold;
  font-family: 'Muli', sans-serif;
  height: 50px;
  letter-spacing: 1px;
  margin: 10px 0px;
}



Para no tener que abrir otro tab u otra ventana de la terminal solo para levantar el “json-server”, modifica los scripts de tu package.json de esta manera:

    "server": "json-server initialState.json",
    "start": "webpack-dev-server --open --mode development & npm 	 
    run server"

Así, al ejecutar npm start se levantará tanto el servidor de desarrollo como el json-server

Muy dinamicas tus clases. Y es admirable la facilidad para explicar las cosas sin mucho enredo.

Un poco de documentacion para entender un poco devServer: Click Aqui

Les comparto el código css convertido a sass:

Login.scss

.login {
	background-image: linear-gradient(#21c08b, #8f57fd);
	display: flex;
	align-items: center;
	flex-direction: column;
	justify-content: center;
	padding: 0px 30px;
  min-height: calc(100vh - 200px);

  &__container {
    background-color: rgba(255,255,255,0.1);
    border: 2px solid white;
    border-radius: 40px;
    box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
    color: white;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    min-height: 700px;
    padding: 60px 68px 40px;
    width: 300px;

    &--form {
      display: flex;
      flex-direction: column;
      label {
        font-size: 14px;
      }
    }

    &--remember-me {
      color: white;
      display: flex;
      justify-content: space-between;
      margin-top: 10px;
      a {
        color: white;
        font-size: 14px;
        text-decoration: none;
        &:hover {
          text-decoration: underline;
        }
      }
    }

    &--social-media {
      >div {
        align-items: center;
        display: flex;
        font-size: 14px;
        margin-bottom: 10px;
        >img {
          margin-right: 10px;
          width: 30px;
        }
      }
    }

    &--register {
      font-size: 14px;
      a {
        color: white;
        font-weight: bold;
        font-size: 16px;
        text-decoration: none;
        &:hover {
          text-decoration: underline;
        }
      }
    }

  }
}

Para abrir una sola terminal y correr el json-server y nuestro proyecto podemos instalar el paquete concurrently: npm install concurrently --save-dev
Y después agregamos estos scripts en el archivo package.json en la zona de scripts:
“server”: “json-server initialState.json”,
“dev”: “webpack-dev-server --open --mode development”,
“start”: “concurrently “npm run server” “npm run dev””,
de este modo al dar npm run start se abren el json-server y nuestro proyecto desde una sola terminal.

Container: Login

Creamos el componente para el Login; lo hacemos en los contenedores como componente presentacional; usamos las imágenes; creamos los estilos.

Importamos nuestro componentes a nuestro archivo de rutas; lo añadimos a una ruta.

<Rute exact path="/login" component={Login} />

Antes de plugins en el archivo de configuración de webpack debemos colocar lo siguiente para trabajar con rutas e historias en el navegador.

devServer: {
    historyApiFallback:true,
}
Captura de pantalla de 2020-05-02 21-32-10.png

Esa configuración de web pack solo aplica en desarrollo, ¿Pero en producción ya no es necesario agregar algo mas?

Que tal, para aquellos que tengan errores con el archivo de eslint que se dio en el curso de React Practico, lo estuve revisando y solvente todos los errores, aqui les dejo el link del gist que hice: https://gist.github.com/matias4205/e623b25c1f3c3859a072d9a98d8c1b10

Come se relaciona esto con el back end. O ya utilizando estas herramientas estamos reemplazando el back end

En Vscode existe una extensión llamada.

html to jsx

Muy buena para estos casos en los que estas pasando contenido de HTML a JSX!!

De esta forma carga automáticamente la App después del npm run start.

  devServer: {
    open: true,
    hot: true,
    port: 8081,
    historyApiFallback: true,
  },

Oscar hay que trabajar en pedagogía.

Se puede tener conocimiento de algún tema y para saberlo transmitir hay que aplicar pedagogía y una buena estructura de planeación de lo que se va a enseñar,

Muchos cursos de Platzi fallan en este punto.

Mi diseño se estaba viendo así:Captura de pantalla (355).png
y lo resolví solo eliminando una línea de Css
Captura de pantalla (354).png

.login__container{
    background-color: rgba(255, 255, 255, 0.1);
    border: 2px solid white;
    border-radius: 40px;
    color: white;
    padding: 60px 68px 40px;
    // width: 300px; //Esta línea
    min-height: 700px;
    display: flex;
    justify-content: space-around;
    flex-direction: column;
}

Como hacer para que salga el emoji a mi tambien??

Muy buena clase.

IMAGE 2020-08-12 18:44:22.jpg
const app = () => (
    <BrowserRouter>
        <Route exact path="/" component={Home} />
        <Route exact path="/login" component={Login} />
    </BrowserRouter>
);

Tengo la misma configuración de Eslint y me aparecen muchos “errores” que al profe no le aparece, lo mismo me pasaba en el curso pasado ): Más allá del origen de lo que produce el error mi pregunta es porqué a mi me aparecen y al profe no teniendo exactamente el mismo .eslintrc, mi node corre sobre WSL (Ubuntu), últimas versiones de todo

Pregunta.
Me ha salido el siguiente error y no se como solucionarlo Captura de Pantalla 2020-04-13 a la(s) 10.56.40.png
Ya llevo dos días y no puedo pasar de este tema, me he regresado y he visto el siguiente y sigo con el mismo error. alguien que me pueda ayudar por favor.

Adjunto mi repositorio : https://github.com/SoterRamirez/EducVideo/tree/feature/router-redux
Desde ya, muchas gracias por su ayuda.

Yo estoy practicando, uso un archivo webpack.config.dev.js y esta solucion del profe no me funciono, lei la documentacion y encontre que escribiendo lo siguiente en el archivo webpack.config.dev.js funciona perfectamente.

  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    stats: 'errors-only',
    open: true,
    port: 3006,
    compress: true,
    historyApiFallback: true,
  },

les comparto el codigo de esta clase
Login.jsx

import React from "react";
import "../assets/styles/components/Login.scss";
import googleIcon from "../assets/static/google-icon.png";
import twitterIcon from "../assets/static/twitter-icon.png";

const Login = () => {
	return (
		<section className="login">
			<section className="login__container">
				<h2>Inicia sesión</h2>
				<form className="login__container--form">
					<input className="input" type="text" placeholder="Correo" />
					<input className="input" type="password" placeholder="Contraseña" />
					<button className="button">Iniciar sesión</button>
					<div className="login__container--remember-me">
						<label>
							<input type="checkbox" id="cbox1" value="first_checkbox" />
							Recuérdame
						</label>
						<a href="/">Olvidé mi contraseña</a>
					</div>
				</form>
				<section className="login__container--social-media">
					<div>
						<img src={googleIcon} /> Inicia sesión con Google
					</div>
					<div>
						<img src={twitterIcon} /> Inicia sesión con Twitter
					</div>
				</section>
				<p className="login__container--register">
					No tienes ninguna cuenta <a href="">Regístrate</a>
				</p>
			</section>
		</section>
	);
};

export default Login;

Login.scss

.login {
	background-image: linear-gradient(#21c08b, #8f57fd);
	display: flex;
	align-items: center;
	flex-direction: column;
	justify-content: center;
	padding: 0px 30px;
	min-height: calc(
		100vh - 200px
	); /* El ancho será igual al tamaño de todo el height menos 200px (100px del header + 100px del footer) */
}

.login__container {
	background-color: rgba(255, 255, 255, 0.1);
	border: 2px solid white;
	border-radius: 40px;
	box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
	color: white;
	display: flex;
	flex-direction: column;
	justify-content: space-around;
	min-height: 700px;
	padding: 60px 68px 40px;
	width: 300px;
}

.login__container--form {
	display: flex;
	flex-direction: column;
}

.login__container--form label {
	font-size: 14px;
}

.login__container--remember-me {
	color: white;
	display: flex;
	justify-content: space-between;
	margin-top: 10px;
}

.login__container--remember-me a {
	color: white;
	font-size: 14px;
	text-decoration: none;
}

.login__container--remember-me a:hover {
	text-decoration: underline;
}

.login__container--social-media > div {
	align-items: center;
	display: flex;
	font-size: 14px;
	margin-bottom: 10px;
}

.login__container--social-media > div > img {
	margin-right: 10px;
	width: 30px;
}

.login__container--register {
	font-size: 14px;
}

.login__container--register a {
	color: white;
	font-weight: bold;
	font-size: 16px;
	text-decoration: none;
}

.login__container--register a:hover {
	text-decoration: underline;
}

routes/App.js

import React from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Home from "../containers/Home";
import Login from "../containers/Login";
const App = () => {
	return (
		<BrowserRouter>
			<Route exact path="/" component={Home} />
			<Route exact path="/login" component={Login} />
		</BrowserRouter>
	);
};

export default App;

webpack.config.js

const path = require("path");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
	entry: "./src/index.js",
	output: {
		path: path.resolve(__dirname, "dist"),
		filename: "bundle.js",
	},
	resolve: {
		extensions: [".js", ".jsx"],
	},
	module: {
		rules: [
			{
				test: /\.(js|jsx)$/,
				exclude: /node_modules/,
				use: {
					loader: "babel-loader",
				},
			},
			{
				test: /\.html$/,
				use: [
					{
						loader: "html-loader",
					},
				],
			},
			{
				test: /\.(s*)css$/,
				use: [
					{
						loader: MiniCssExtractPlugin.loader,
					},
					"css-loader",
					"sass-loader",
				],
			},
			{
				test: /\.(png|gif|jpg)$/,
				use: [
					{
						loader: "file-loader",
						options: {
							name: "assets/[hash].[ext]",
						},
					},
				],
			},
		],
	},
	devServer: {
		historyApiFallback: true,
	},
	plugins: [
		new HtmlWebPackPlugin({
			template: "./public/index.html",
			filename: "./index.html",
		}),
		new MiniCssExtractPlugin({
			filename: "assets/[name].css",
		}),
	],
};

Buenas, que debo hacer para solucionar el error con los archivos .json

Uncaught Error: Cannot find module './translationses.json'
    at webpackContextResolve (.json$:13)
    at webpackContext (.json$:8)
    at App (App.js:14)
    at renderWithHooks (react-dom.development.js:14803)
    at mountIndeterminateComponent (react-dom.development.js:17482)
    at beginWork (react-dom.development.js:18596)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at beginWork$1 (react-dom.development.js:23203)

gracias…

Me encanta la seguidilla de cursos pero todavía no entiendo para que dedicarle tanto tiempo a la configuración manual del webpack

El historyApiFallback: true de React Router es un simil de mode: ‘history’, en Vuejs. ? o cumplen finalidades distintas

Los primeros pasos con Router, buenisimo!

woooo, excelente clase 😄

Sigo sin poder hacer match con login

que bueno es volver a ver el curso y en practica mucho mejor

Vengo del curso Practico de React, con mi proyecto de Platzi video sin errores ejecutándose correctamente.
Tengo todo correcto en código fuente no hay errores sin embargo al ejecutar
npm run start

react.development.js:167 Warning: React.createElement: type is invalid – expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.
Check the render method of App.
in App

Aparece el error descrito arriba, ya revise todo estoy haciendo bien las exportaciones
Investigando aplique la solución que aparece en esta URL
https://platzi.com/clases/1079-react-2016/6326-actualizando-a-la-ultima-version-de-react-router/
luego ejecuto nuevamente npm run start y me pedia instalar react-router
npm install --save react-router
pero al final regresa al mismo error
Check the render method of App.
in App

He aquí la documentación del api de DevServer historyApiFallback

Buena clase.

hola…me aparece esta advertencia:

Advertencia internal-error (ESLint) Failed to load config “prettier” to extend from.

¿Alguna idea de porqué será?

WhatsApp Image 2020-04-19 at 12.31.39 PM.png

Listo me toé con varios errores pero quedo todo bien hasta esta parte

me surge una duda. ¿Hay algun problema si se deja el Archivo App con extension JSX?

Debemos modificar nuestra configuración del entorno de desarrollo local para que pueda funcionar con el uso de rutas, debemos ir al archivo webpack.config.js y añadir este fragmento de código antes de plugins:

module.exports = {
{//}
devServer: {
historyApiFallback: true,
},
{//}
}

Alguien sabe por que cuando corro la aplicacion, se renderizan las dos rutas en la misma pantalla Captura de pantalla de 2020-06-24 17-26-10.png

Que buena explicación por parte de Oscar.

Hola Todos, este es mi código!!!







No me gusta que va copiando codigo, esa no es la idea de un curso.

Muy buena clase.

IMAGE 2020-08-11 20:34:29.jpg

Al agregar la configuración del devServer me sale el siguiente error
errorDevServer.png

Otra solución para correr el servidor jason sin usar otra consola u otro tab es instalar la dependencia npm-run-all y modificar lo siguiente en tu archivo jason:

"client": "webpack-dev-server --open --mode development",
 "server": "json-server --port 3001 --watch initialState.json",
 "start": "npm-run-all -p client server",

Cuando manejamos nuestro entorno de desarrollo local, debemos hacer que pueda manejar las rutas. Hacemos esto en el archivo de webpack.config.js

devServer: {
    historyApiFallback: true,
  }

import de las imagenes

import googleIcon from "../assets/static/google-icon.png"
import twitterIcon from "../assets/static/twitter-icon.png"

Pueden utilizar este convertidor de HTML a JSX si su editor les marca error

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <!-- Font -->
  <link href="https://fonts.googleapis.com/css?family=Muli&display=swap" rel="stylesheet">
  <!-- Styles -->
  <link rel="stylesheet" href="./styles.css">
  <!-- Title -->
  <title>Inicia Sesión</title>
</head>
<body>
  <header class="header">
    <img class="header__img" src="../assets/logo-platzi-video-BW2.png" alt="Platzi Video">
  </header>
  <section class="login">
    <section class="login__container">
      <h2>Inicia sesión</h2>
      <form class="login__container--form">
        <input class="input" type="text" placeholder="Correo">
        <input class="input" type="password" placeholder="Contraseña">
        <button class="button">Iniciar sesión</button>
        <div class="login__container--remember-me">
          <label>
            <input type="checkbox" id="cbox1" value="first_checkbox">Recuérdame
          </label>
          <a href="/">Olvidé mi contraseña</a>
        </div>
      </form>
      <section class="login__container--social-media">
        <div><img src="../assets/google-icon.png"> Inicia sesión con Google</div>
        <div><img src="../assets/twitter-icon.png"> Inicia sesión con Twitter</div>
      </section>
      <p class="login__container--register">No tienes ninguna cuenta <a href="">Regístrate</a></p>
    </section>
  </section>
  <footer class="footer">
    <a href="/">Terminos de uso</a>
    <a href="/">Declaración de privacidad</a>
    <a href="/">Centro de ayuda</a>
  </footer>
</body>
</html>```

Me estaba saliendo este error. err.PNG

Luego de ver dos veces el video, me di cuenta que al definir la constante Login en Login.jsx todo es con paréntesis y yo lo había hecho con llaves lo que abarca la “section”. Ahora todo OK. 😉

Así es como tengo a Login.jsx

import React from 'react';
import googleIcon from '../assets/static/google-icon.png';
import twitterIcon from '../assets/static/twitter-icon.png';
import '../assets/styles/components/Login.scss';

const Login = () => (
<section className='login'>
    <section className='login__container'>
      <h2>Inicia sesión</h2>
      <form className='login__container--form'>
        <input className='input' type='text' placeholder='Correo' />
        <input className='input' type='password' placeholder='Contraseña' />
        <button className='button'>Iniciar sesión</button>
        <div className='login__container--remember-me'>
          <label>
            <input type='checkbox' id='cbox1' value='first_checkbox' />
            Recuérdame
          </label>
          <a href='/'>
            Olvidé mi contraseña
          </a>
        </div>
      </form>
      <section className='login__container--social-media'>
        <div><img src={googleIcon} /> Inicia sesión con Google</div>
        <div><img src={twitterIcon} /> Inicia sesión con Twitter</div>
      </section>
      <p className='login__container--register'>No tienes ninguna cuenta <a href=''>Regístrate</a></p>
    </section>
</section>
);
export default Login;

import React from "react";

const Login = () => {
  return (
    <section className="login">
      <section className="login__container">
        <h2>Inicia sesión</h2>
        <form className="login__container--form">
          <input className="input" type="text" placeholder="Correo" />
          <input className="input" type="password" placeholder="Contraseña" />
          <button className="button">Iniciar sesión</button>
          <div className="login__container--remember-me">
            <label>
              <input type="checkbox" id="cbox1" value="first_checkbox" />
              Recuérdame
            </label>
            <a href="/">Olvidé mi contraseña</a>
          </div>
        </form>
        <section className="login__container--social-media">
          <div>
            <img src="../assets/google-icon.png" /> Inicia sesión con Google
          </div>
          <div>
            <img src="../assets/twitter-icon.png" /> Inicia sesión con Twitter
          </div>
        </section>
        <p className="login__container--register">
          No tienes ninguna cuenta <a href="">Regístrate</a>
        </p>
      </section>
    </section>
  );
};
export default Login;

.

El componente es similar a un elemento ya que nos permite navegar dentro de la aplicación, pero sin necesidad de recargar la página. Para indicar el destino, simplemente pasamos el prop a = ‘/ my-link’.

Primero importe el enlace desde react-router-dom. Agregue la etiqueta de enlace a la etiqueta de anclajes de la imagen del logotipo, también con la cuenta y la sección de cierre.

Además, necesitamos implementar el componente Link en nuestro contenedor de inicio de sesión.

![](l1png.png

Genial!

Para entender por qué se coloca historyApiFallback en el webpack

Práctica:
2.PNG