Crea una cuenta o inicia sesión

¡Continúa aprendiendo sin ningún costo! Únete y comienza a potenciar tu carrera

Curso de React Router 5 y Redux

Curso de React Router 5 y Redux

Oscar Barajas Tavares

Oscar Barajas Tavares

Container: Login

4/29
Recursos

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,  
  },
  {/*...*/}
}

Aportes 57

Preguntas 16

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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.

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,
}

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.

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;
        }
      }
    }

  }
}

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.

const app = () => (
    <BrowserRouter>
        <Route exact path="/" component={Home} />
        <Route exact path="/login" component={Login} />
    </BrowserRouter>
);

Mi diseño se estaba viendo así:
y lo resolví solo eliminando una línea de Css

.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;
}

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

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

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

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

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

Deberian actualizar este curso porque React Router ya cambio:

import React from “react”;
import { BrowserRouter, Route, Routes } from “react-router-dom”;
import Home from “…/containers/Home”;

const App = () => (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</BrowserRouter>
);

export default App;

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

Muy buena clase.

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!!

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,
  },

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

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

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

Sigo sin poder hacer match con login

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

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

Muy buena clase.

Buena clase.

hola…me aparece esta advertencia:

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

¿Alguna idea de porqué será?

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

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

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,
},
{//}
}

Que buena explicación por parte de Oscar.

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",

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…

Yo tengo poco menos de 2 años con React y veo algunas cosas que no conoci en su momento, pero es buen entender algo de codigo legacy por eso de que toque trabajar y actualizar a versiones recientes.

woooo, excelente clase 😄

Los primeros pasos con Router, buenisimo!

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",
		}),
	],
};

Ya que estamos manejando diferentes rutas necesitamos preparar nuestro proyecto para poder manejarla. Ya que tengamos nuestro componente solo tenemos que agregarlo a las rutas, en caso de que nos marque error es porque no hemos configurado el webpack para manejo de rutas internas, esto solo despues de plugins le agregamos un:

devServer: {
        historyApiFallback: true,
    },

Y ya agregamos la nueva ruta como lo hicimos anteriomente:

<Route exact path="/login" component={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='../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>e> 

en mi caso lo que hice fue crear un componente LoginForm donde estaba el formulario y y un componente presentacional para mostrarlo iigual que home.
la diferencia entre ambos es que en login no se muestra el div “mi perfil” lo que hice fue agregar una condicional

{window.location.pathname !== ‘/login’ && (
div menu perfil
)

y con esto ya se ve igual que en el html

Visual Studio Code tiene una terminal integrada pulsando Ctrl + ñ. Pueden abrirse varias Tabs.

Si notas que tu componente login.jsx no se renderiza es porque debes importar las rutas en tu archivo index.js

import React from 'react';
import ReactDOM from 'react-dom';

import App from './routes/App';

ReactDOM.render(<App />, document.getElementById('app'));

No encuentro ninguno de los cursos que mencionan desde el inicio de este curso, quería entender mejor como se realizaron los proyectos, me está mareando mucho.

Me estaba saliendo este error.

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. 😉

<!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>```

Práctica:

Genial!

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;

import de las imagenes

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

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.

.

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;

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,
  }

![](