Wow, tenía rato que no veía a alguien que explicara tan bien, esto se me hacia super complejo pero con Rodolfo queda bastante claro!
Bienvenido al curso
Conoce a tu profesor y todo lo que aprenderás sobre Redux
¿Qué conocimientos me recomiendan para tomar este curso?
Repaso React
¿Qué es React y cómo funciona?
Preparando nuestro entorno de trabajo
Creación de la app con React
Agregando funciones a la app con React
Stateful vs Stateless
Ciclo de vida de React
Manejando promesas
React Router DOM
Introducción a Redux
¿Qúe es Redux, cuándo usarlo y por qué?
Fases de Redux
Introducción: las fases de Redux
Store
Reducers
Conexión a un componente
Action Creators
Redux Thunk
Explicación teórica: ciclo completo de Redux
Práctica: ciclo completo de Redux
Fases Extra
Archivos Types
Try Catch
Escenarios asíncronos
Componente Spinner
Componente Fatal
Tabla como componente
Compartir información en Redux
Introducción Compartir información en Redux
Parámetros por URL
Compartir Reducer
Múltiples Reducers
Llamando a múltiples reducers en una acción
Uso del estado en la acción
Evitar segundas búsquedas
Inmutabilidad
Evitar sobrescritura
Validación compuesta
Validación de errores
Modificando respuesta de url
Estado con interacción
Mostrar componentes dinámicamente
Llamadas asincronas dinámicas
Props por herencia vs estado
Estado compartido
Métodos HTTP
Introducción a métodos HTTP
Nuevo ciclo Redux
Normalizar datos
Mapear Objetos
Componente para agregar tarea
Manejar inputs con Reducer
POST
Deshabilitando botón
Redireccionar
Reutilizar componentes
PUT
DELETE
Últimos detalles
Conclusión
Conocimientos adquiridos
Qué hacer a continuación
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 33
Preguntas 4
Wow, tenía rato que no veía a alguien que explicara tan bien, esto se me hacia super complejo pero con Rodolfo queda bastante claro!
Se me hace mas facil crear un objeto que contenga todas las constantes de los Action, a continuacion el codigo
actionType.js
export const actionType = {
SET_INITIAL_STATE: "SET_INITIAL_STATE",
LOADING: "LOADING"
};
Reducer.js
export default (state = SET_INITIAL_STATE, action) => {
switch (action.type) {
case actionType.SET_INITIAL_STATE:
return {
...state,
aboutMe: action.payload.aboutMe,
firebase: action.payload.firebase,
user: action.payload.user
};
case actionType.LOADING:
return {
...state,
loading: true
};
default:
return state;
}
};
Action.js
export const setInititalState = () => dispatch => {
dispatch({
type: actionType.LOADING
});
try {
dispatch({
type: actionType.SET_INITIAL_STATE,
payload: {
aboutMe: { ...aboutMe },
firebase: { ...firebaseRef },
user: {}
}
});
} catch (error) {
console.log(error.message);
}
};```
Es cuestión de ver que escribimos la palabra async y enseguida pensar en los 3 estados
No me parece que sea necesario hacer un reducer, action y type solo para indicar que la página esta cargando. En realidad la propiedad “loading” no necesita ser global, se puede manejar localmente de la siguiente forma:
class Usuarios extends Component {
constructor(){
super();
this.state = { loading: true }; //indicamos que el componente inicia cargando.
}
async componentDidMount(){
await this.props.traerTodos();//esperamos a que carguen los datos.
this.setState({loading: false});//dejamos de cargar al recibir los datos.
}
render(){
if(this.state.loading) return 'Loading...';//si los datos están cargando, mostramos un mensaje.
return (
//al terminar la carga, se mostrará la página.
);
}
}
Vaya todo empieza a tomar forma, Vi esto anteriormente y lo comprendía de manera muy superficial. Ahora entiendo mas a profundidad.
Hola Devs:
-Aqui les comparto mi avance, con mi respectiva manera:
Mi archivo principal Users:
Mis Actions:
Mis Reducers:
Recuerda, #NuncaParesDeAprender 💚
Me encanta como se pueden comunicar entre ellos.
Y en ves de poner simplemente mensajes asi como esos se puede poner toda una interfaz en el cargando o en el errror?
Comparto mi solucion, contiene el manejo de los tres casos: loading, fetch y error. tambien le puse un timeout para simular un tiempo de demora consultanod la api, asi se aprecia mas el componente loading.
usersActionsCreator.js >>
import { FETCH_USERS, LOADING_USERS, ERROR_USERS } from "./actionTypes";
import Axios from 'axios';
/**
* Action creator para usuarios
* @returns distpatch varias acciones
*/
export const fetchUsers = () => (distpatch) =>{
//Le comunica al reducer los diferentes casos
distpatch({
type: LOADING_USERS,
})
setTimeout( async ()=>{
try {
const response = await Axios({
url: "https://jsonplaceholder.typicode.com/users",
});
distpatch({
type: FETCH_USERS,
payload: response.data
})
} catch (error) {
distpatch({
type: ERROR_USERS,
payload: error
})
}
}, 1000 );
}
export const getUsers = () => () =>{
console.log('esto podria ser otra funcion ... trayendo ususaios');
}
usersReducer.js >>
import { FETCH_USERS, LOADING_USERS, ERROR_USERS } from "../Actions/actionTypes";
const INITIAL_STATE = {
users: [],
loading: false,
error: ''
};
/**
* Reducer: Dependiendo de cada caso, actualiza los estados
*/
// eslint-disable-next-line import/no-anonymous-default-export
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case LOADING_USERS:
return {
...state,
loading: true
}
case FETCH_USERS:
return {
...state,
users: action.payload,
loading: false
}
case ERROR_USERS:
return {
...state,
error: action.payload,
loading: false
}
default:
return state
}
}
actionTypes.js >>
export const FETCH_USERS = 'fetch_all_users';
export const LOADING_USERS = 'loading_users';
export const ERROR_USERS = 'error_users';
Siempre debemos de manejar los casos de:
Nuestro sitio está cargando información cuando entramos a una página.
Lo que haremos es mostrar cuando la información está cargando, cuando hay éxito y cuando hay error:
usuariosTypes.js:
export const TRAER_TODOS = 'traer_todos';
export const CARGANDO = 'cargando';
export const ERROR = 'error';
usuariosReducers.js:
import { TRAER_TODOS, CARGANDO, ERROR } from '../types/usuariosTypes';
const INITIAL_STATE = {
usuarios: [],
cargando: false,
error: ''
};
export default (state = INITIAL_STATE, action) => { //* El estado es el initial state que regresa una función
//!Se crea el switch porque llegarán varias tareas y solo se distingue por el nombre
switch(action.type) {
case TRAER_TODOS:
return { ...state, usuarios: action.payload, cargando: false };
case CARGANDO:
return { ...state, cargando: true};
case ERROR:
return { ...state, error: action.payload, cargando: false };
default: return state;
}
}
usuariosActions.js:
import axios from 'axios';
import { TRAER_TODOS, CARGANDO, ERROR } from '../types/usuariosTypes';
//*Esto es una promesa por estar haciendo una petición HTTP GET
export const traerTodos = () => async (dispatch) => { //* Función que retorna otra función
dispatch({
type: CARGANDO
});
try {
const respuesta = await axios.get('https://jsonplaceholder.typicode.com/users');
dispatch({ //* Este dispatch se comunicará con el reducer
type: TRAER_TODOS,
payload: respuesta.data,
});
} catch (error) {
console.error(`Error: ${error.message}`);
dispatch({
type: ERROR,
payload: error.message,
})
}
}
Genial los casos obligatorios a controlar de una llamada asíncrona:
Muy buena practica
Va excelente este curso. bastante claro.
Excelente clase
Excelente clase 👏
Excelente
Muy Buena explicación. Buena clase.
Excellent, esto lo estaba preguntando unas clases antes, come On !!
Buena explicación 😄
Excelente
Excelente clase. A seguir practicando y aprendiendo. 🙂
Buen ejercicio 😄
Mis console log se repiten el doble de veces 😦
Alguine sabe que onda?
me traer undefined en el estado de loading, comparto mi codigo ya que de aqui no he podido avanzar
userTypes
export const TRAER_TODOS = "_traer_users_"
export const CARGANDO = "cargando"
ahora mi usersActions
import axios from "axios";
import { TRAER_TODOS, CARGANDO } from "../types/usersTypes";
//promesa para la peticion get y al reducer le entrego con los datos con el getResponse.data
export const traerTodos = () => async (dispatch) => {
dispatch({
type: CARGANDO,
});
try {
const getResponse = await axios.get(
"https://jsonplaceholder.typicode.com/users"
);
dispatch({
type: TRAER_TODOS,
payload: getResponse.data,
});
} catch (err) {
console.log("Error: ", err.message);
}
};
usuariosReducers
import { TRAER_TODOS, CARGANDO } from "../types/usersTypes";
const INITIAL_STATE = {
users: [],
cargando: false,
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case TRAER_TODOS:
return {
...state,
users: action.payload,
cargando: false,
};
case CARGANDO:
return {
...state,
cargando: true,
};
default:
return state;
}
};
de ultimo la respuesta de la consola:
También agregué el error en el action de get_all_users:
si por ejemplo… llegaron los datos, se va la señal, y luego vuelve la señal, nos va a mostrar que, aunque ya no hay error y trajo los datos, en los props el error quedó pegado. Por eso debemos actualizar también el error en esa acción:
// usersReducer.js
import { GET_USERS, LOADING, ERROR } from '../types/usersTypes';
const INITIAL_STATE = {
users: [],
loading: false,
error: ''
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case GET_USERS:
return {
...state,
users: action.payload,
loading: false,
error: ''
}
case LOADING:
return {
...state,
loading: true
}
case ERROR:
return {
...state,
error: action.payload,
loading: false
}
default: return state;
};
};
// usersActions.js
import axios from 'axios';
import { GET_USERS, LOADING, ERROR } from '../types/usersTypes';
const API_URL = 'https://jsonplaceholder.typicode.com/users';
export const getUsers = () => {
return async (dispatch) => {
dispatch({
type: LOADING
})
try {
const response = await axios.get(API_URL);
dispatch({
type: GET_USERS,
payload: response.data
});
} catch (err) {
new Error(console.error('Error occured: ',err.message));
dispatch({
type: ERROR,
loading: false,
payload: err.message,
});
}
}
}
Con ayuda de las DevTools podemos reducir la velocidad de conexión del browser para tener una mejor idea de cómo funciona nuestro sitio en conexiones lentas o incluso offline.
me marea esto del dispatch
Al principio pensaba que se hacia mucho para tener el estado de cargando
y error
ya que lo tenia todo dentro del action traer_todos
y funcionaba. Pero separando las acciones es más sencillo leer el código. Muy buena clase.
Antes
switch (action.type) {
case TRAER_TODOS:
return {
...state,
loading: action.payload.loading,
error: action.payload.error,
users: action.payload.users,
}
default: return state
}
despues
switch (action.type) {
case TRAER_TODOS:
return {
...state,
users: action.payload,
loading: false,
error: null,
}
case CARGANDO:
return {
...state,
loading: true
}
case ERROR:
return {
...state,
error: action.payload,
loading: false,
users: null,
}
default: return state
}
Creo que invertiré algo de tiempo en hacer los mensajes a nivel front ya que están listos los estados
Si alguien esta usando fetch con el try catch algo asi:
import { GET_ALL, LOADING, ERROR } from '../types/usersTypes'
export const getAll = () => async (dispatch) => {
dispatch({
type: LOADING,
})
try {
const response = await fetch('https://jsonplaceholder.typicode.com/usesrs')
console.log('entro', response)
const users = await response.json()
dispatch({
type: GET_ALL,
payload: users,
})
} catch (error) {
console.log('Error: ', error.message)
dispatch({
type: ERROR,
payload: error.message,
})
}
}
probablemente el catch no esta tomando el error, eso es por que para fetch 404 es solo un response status, parar el no es un error, para poder que tome el 404 como error hay que definirlo como tal con un
throw new Error(response.statusText);
Algo asi
import { GET_ALL, LOADING, ERROR } from '../types/usersTypes'
export const getAll = () => async (dispatch) => {
dispatch({
type: LOADING,
})
try {
const response = await fetch('https://jsonplaceholder.typicode.com/usesrs')
if (!response.ok) {
throw new Error('Error to fetch data')
}
const users = await response.json()
dispatch({
type: GET_ALL,
payload: users,
})
} catch (error) {
console.log(error)
dispatch({
type: ERROR,
payload: error,
})
}
}
En la seccion anterior, estaba un poco perdido, pero con el flujo teorico y practico, se afianzan mas los conocimientos. Excelente profe!!!
Un capo este profesor!
No acabo de entender de donde se le pasa el parámetro dispatch a usuariosAction.js.
Alguien que me pueda explicar?
Saludos y se les agradece.😀
Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.