Bienvenido al curso

1

Conoce a tu profesor y todo lo que aprenderás sobre Redux

2

¿Qué conocimientos me recomiendan para tomar este curso?

Repaso React

3

¿Qué es React y cómo funciona?

4

Preparando nuestro entorno de trabajo

5

Creación de la app con React

6

Agregando funciones a la app con React

7

Stateful vs Stateless

8

Ciclo de vida de React

9

Manejando promesas

10

React Router DOM

Introducción a Redux

11

¿Qúe es Redux, cuándo usarlo y por qué?

Fases de Redux

12

Introducción: las fases de Redux

13

Store

14

Reducers

15

Conexión a un componente

16

Action Creators

17

Redux Thunk

18

Explicación teórica: ciclo completo de Redux

19

Práctica: ciclo completo de Redux

Fases Extra

20

Archivos Types

21

Try Catch

22

Escenarios asíncronos

23

Componente Spinner

24

Componente Fatal

25

Tabla como componente

Compartir información en Redux

26

Introducción Compartir información en Redux

27

Parámetros por URL

28

Compartir Reducer

29

Múltiples Reducers

30

Llamando a múltiples reducers en una acción

31

Uso del estado en la acción

32

Evitar segundas búsquedas

33

Inmutabilidad

34

Evitar sobrescritura

35

Validación compuesta

36

Validación de errores

37

Modificando respuesta de url

38

Estado con interacción

39

Mostrar componentes dinámicamente

40

Llamadas asincronas dinámicas

41

Props por herencia vs estado

42

Estado compartido

Métodos HTTP

43

Introducción a métodos HTTP

44

Nuevo ciclo Redux

45

Normalizar datos

46

Mapear Objetos

47

Componente para agregar tarea

48

Manejar inputs con Reducer

49

POST

50

Deshabilitando botón

51

Redireccionar

52

Reutilizar componentes

53

PUT

54

DELETE

55

Últimos detalles

Conclusión

56

Conocimientos adquiridos

57

Qué hacer a continuación

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de Redux por Bedu

Curso de Redux por Bedu

Rodolfo Saldivar

Rodolfo Saldivar

Escenarios asíncronos

22/57
Recursos

Aportes 33

Preguntas 4

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

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

Escenarios asíncronos

Siempre debemos de manejar los casos de:

  1. Cuando está cargando
  2. Cuando fue exitoso
  3. Cuando hay un error

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:

  1. Cuando esta cargando
  2. Cuando fue exitoso
  3. Cuando fue un error

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