No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Reg铆strate

Comienza en:

2D
2H
34M
16S
Curso de React Router 5 y Redux

Curso de React Router 5 y Redux

Oscar Barajas Tavares

Oscar Barajas Tavares

Creando los reducers

13/29
Recursos

Un action de Redux va a contener dos elementos:

  • type: para indicar la acci贸n que se va a ejecutar.
  • payload: es la informaci贸n que estamos mandando al reducer.

Dentro de los reducers usaremos un switch para separar la l贸gica por cada tipo de acci贸n que tendremos en Redux.

Aportes 83

Preguntas 34

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

馃槮
Me tom贸 mucho tiempo entender Redux, tuve que volver a reproducir las clases y buscar en internet sobre arreglos y objectos porque no ten铆a ni idea de porque a veces destructurabas o por qu茅, y tampoco ten铆a idea de c贸mo funcionaban los datos y el estado pero ya por fin entend铆.

Tercera vez que miro este video y contando鈥

Despu茅s de repetir las clases, este es mi resumen:

  1. El Storage es como una base de datos de los estados

  2. El connect permite la conexi贸n entre el componente con el Storage y tiene 2 par谩metros. Ejemplo - Connect (Primero,Segundo):

    Primero: Env铆a el estado actual del Storage al componente para que sea utilizado por medio de su props. Para lograrlo, se crea una funci贸n que indicar谩 que atributos se quieren utilizar en el componente y luego las asigna a su props.
    Segundo: Env铆a al Reduce la acci贸n que hemos encapsulado y que, por alguna raz贸n que a煤n no entiendo, al ser llamada por el import en el componente se le atribuye su props. Cuando esta acci贸n llega al Reduce, es identificada mediante el Switch por su atributo Type para su ejecuci贸n. Luego, el Reduce env铆a el resultado al Storage para su actualizaci贸n.
    Importante: El Reduce tambi茅n tiene 2 atributos 鈥(state, action)鈥:

    • state: Es el estado que el Stage env铆a al Reduce. Por lo tanto, es el estado que se va a actualizar.
    • action: Es la acci贸n encapsulada que fue enviada por el componente al Reduce para que se actualice el estado del Stage.

Espero haberme dejado entender y que a alguien m谩s se sirva para que siga aprendiendo sin muchas dudas en las siguientes clases.

Mencionar que si les surge un error de que cada item deberia tener una key, es porque no lo estamos mandando en el payload de setFavorite en CarouselItem, con esto lo pueden solucionar:

` const {id, cover, title, year, contentRating, duration } = props

const handleSetFavorite = () => {
    props.setFavorite({
        id,
        cover,
        title,
        year,
        contentRating,
        duration
    })
}

`

solo es de recibir y enviar el id

Con este video entend铆 como funciona todo, no es necesario hagan el ejercicio yo solo mire los primeros 30 min y fue suficiente para entender como funcionaba todo
Click para ir al video

Espero les sirva de algo

Para elementos repetidos dentro del array, yo hice lo siguiente , modifiqu茅 el reducer para filtrar si existe ese elemento dentro del state.myList.

 case 'SET_FAVORITE':
      if (state.myList.filter((element) => element.id == action.payload.id).length !== 0) {
        return state;
      }
      return {
        ...state,
        myList: [...state.myList, action.payload],
      };

Les comparto para evitar que se agregue un item duplicado al array mylist (Esta es mi manera de hacerlo tal vez haya alguna mejor por favor comentarla si es as铆.)

const { id, cover, title, year, contentRating, duration, setFavorite, mylist } = props
    
const handleSetFavorite = () =>{
        const exist = mylist.find(item => item.id == id)
        if(exist){
            alert("Ya tienes agregado a favorito");  
        }else{
            setFavorite({
                id,
                cover, 
                title, 
                year, 
                contentRating, 
                duration
            })
        }
    }

recuerden agregar el mapStateToProps para acceder a mylist

const mapStateToProps = (state) => {
    return {
        mylist : state.mylist
    }
}


export default connect(mapStateToProps, mapDispatchToProps)(CarouselItem)

<h1>intento mio de entender el proceso de redux</h1>
<h3>Creando reducers en React</h3>

En esta ocasi贸n vamos a guardar los favoritos que agreguemos con el boton de a帽adir a favoritos de nuestra interfaz. Para ello comenzamos creando y exportando la funci贸n setFavorite de nuestro archivo de actions:

export const setFavorite = payload =>({ // Retornamos y exportamos la funci贸n un objeto
	type: 'SET_FAVORITE', // Este es el nombre/descripci贸n que le vamos a dar a nuestro action
	payload // El payload se le podr铆a llamar como la acci贸n de la UI
})

Con esto ya tendriamos nuestro archivo de actions listo, ahora debemos ir a nuestro ir a nuestro reducers para manejar la informaci贸n que recibimos.

La funci贸n de Reducer recibe dos parametros que son el state y el action. Con eso claro vamos a hacer una validaci贸n con switch para a帽adir elementos a la myList cuando el action sea el de SET_FAVORITE:

NOTA: Recordar que los parametros de state y action los conseguimos mas adelante cuando hagamos el connect con nuestra funci贸n setFavorite.

const reducer = (state, action) =>{
	switch(action.type){ // Vamos a validar el type que habimaos mencionado que es como la descripci贸n del action
		case 'SET_FAVORITE'
		return{
			...state, // Desestructuramos la variable state
			myList = [...state.myList, action.payload] // Asignamos nuevos valores a mylist que fueron los que se trajeron del action. Si no desestructuramos la myList se sobrescribiran y no se a帽adiran nuevos favoritos
		}
		default // Caso por defecto si no cumple el action con ninguno
		return state
	}
}

Ya con estos dos archivos listos nos dirigimos al componente donde tengamos nuestro videoItem

Lo primero que debemos hacer es importar connect y exportar nuevamente pero con la funci贸n de connect:

import {connect} from 'react-redux'

...

export default connect(null, mapDispatchToProps)(videoItem) // El primer parametro va null porque no vamos a solicitar props sino vamos a enviarlos

Ahora debemos definir nuestro mapDispatchToProps con nuestro action a enviar*馃槜

const mapDispatchToProps = {
	setFavorite
}

Para hacer esto tambi茅n hay que importar setFavorite de actions:

import {setFavorite} from '../actions'

Ya con esto tendriamos que definir nuestra funci贸n manejadora que se llamar铆a handleSetFavorite y la creamos dentro de nuestro componente:

let videoItem = props => {
	let { img, title, etc} = props
	let handleSetFavorite = () => {
		props.setFavorite({img, title, etc})
	}
}

Se me hizo interesante el 鈥Snake case鈥, no sab铆a que ten铆a un nombre, s贸lo conoc铆a el Camel Case.

Para quien le interese, hay m谩s tipos de case:

  • camelCase

Raw: user login count
Camel Case: userLoginCount

  • PascalCase

Raw: user login count
Pascal Case: UserLoginCount

  • snake_case

Raw: user login count
Snake Case: user_login_count
Snake Case (All Caps): USER_LOGIN_COUNT

  • kebab-case

Raw: user login count
Kebab Case: user-login-count

Art铆culo completo.

Todo bien. Solo me sale un warning:
鈥渂ackend.js:6 Warning: Each child in a list should have a unique 鈥渒ey鈥 prop.鈥

Me pas茅 un d铆a completo sin entender un bug, y era solamente que en un archivo hab铆a puesto

mylist

y lo correcto era

myList 

馃ぃ

En mi caso como modifiqu茅 el json no pod铆a hacerlo funcionar directamente de la forma que est谩 en el v铆deo. Por lo que tuve que hacer algo que se usa en el curso de Redux con Bedu. que fue mapear mis array de listas, entonces que cuando encontrar谩 a 鈥淢i lista鈥, hiciera push del payload a mi array llamado 鈥渧ideos鈥 que contiene la lista.

Si alguien hizo algo similar a lo que yo hice con el JSON y tiene problemas en esta parte, les dejo mi c贸digo del reducer 馃槂

case 'SET_FAVORITE':
            
            const newLists = state.lists.map(list => {
                let value = {...list}
                if(list.title === "Mi lista"){
                    list.videos.push(action.payload)
                }
                return value
            })

            return {
                ...state,
                lists: newLists
            }

Las Actions describen que algo pas贸, pero no especifican c贸mo cambi贸 el estado de la aplicaci贸n en respuesta. Esto es trabajo de los reducers.

Que diferencia, ahora si entiendo como interactua cada elemento de nuestro componente, para solicitar la ejecuci贸n de una acci贸n hacia nuestro store. La carga util es el dato que modifica el estado de la app.

Buenas Pr谩cticas:
Muchas cosas no est谩n estandarizadas en Redux, por lo que brinda flexibilidad para personalizar las cosas, pero como la mayor铆a de nosotros no queremos una soluci贸n personalizada para cada peque帽o detalle cotidiano, la comunidad tiende a establecer lo que se conoce como 鈥渂uenas pr谩cticas鈥.

Para separar este tipo de datos de los datos normales, se utiliza la propiedad conocida como 鈥減ayload鈥. Ahora, sobre qu茅 podemos pasar po 鈥減ayload鈥 y qu茅 deber铆a estar en el mismo nivel es discutible, pero un est谩ndar popular (recomendado por los documentos oficiales) es 鈥淔lux Standard Action鈥 la Acci贸n est谩ndar de flujo que establece que entre los requisitos oficiales puede agregar un 鈥減ayload鈥 , un 鈥渆rror鈥 o un 鈥渕etapropierty鈥.

**POR TANTO:
**Cualquier informaci贸n sobre la acci贸n que no sea el 鈥渢ype鈥 o 鈥渆stado de la acci贸n鈥 debe ser parte del campo de 鈥減ayload鈥.

A mi me salio el error que decia cada item deberia tener un Key unico.

Esto pasa porque no estamos recibiendo un key en cada CarouselItem, y por lo tanto tampoco estamos enviando un key a myList, entonces ahi es donde nos salta el error.

Adicionalmente, en mi codigo, yo encontre que a lllamar la lista de CarouselItems, no le estaba pasando ningun key ni ningun prop a los CarouselItems de myList en Home, por lo que los items en myList salian con todas sus propiedades undefined .

Todo 茅sto lo podemos solucionar, siguiendo estos pasos:

  1. Asegurarnos de que estamos enviandole un ID (Key unico) y todas las props que necesitamos a cada CarouselItem que llamamos en myList en Home:
<Categories title='My lists'>
          <Carousel>
            {myList.map((item) => (
              <CarouselItem key={item.id} {...item} />
            ))}
          </Carousel>
</Categories>
  1. Verificar que estamos recibiendo un ID (Key unico) para cada CarouselItem y que estemos definiendo un proptype para ID (Key unico) en la declaracion de CarouselItem (src/components/CarouselItem.jsx):
const CarouselItem = (props) => {
  const { id, cover, title, year, contentRating, duration } = props;
CarouselItem.propTypes = {
  id: propTypes.number,
  cover: propTypes.string,
  title: propTypes.string,
  year: propTypes.number,
  contentRating: propTypes.string,
  duration: propTypes.number,
};
  1. Verificar que estemos enviando un ID (Key unico) a nuestro store en la declaracion de CarouselItem (src/components/CarouselItem.jsx):
const handleSetFavorite = () => {
    props.setFavorite({
      id,
      cover,
      title,
      year,
      contentRating,
      duration,
    });
  };

Espero que a alguien le sirva 馃槄

Estuve much铆simo tiempo tratando de arreglar un bug y result贸 que hab铆a escrito myList.lenght en vez de **myList.length **

Para el error de two childrens duplicados, la solucion en el Home, basta con agregar un segundo argumento en .map, no se olviden de encerrar ambos argumentos entre parentesis:

return (
    <>
      <Search />
      {myList.length > 0 &&
        <Categories title="Mi Lista">
          <Carousel>
            {myList.map((item, id) =>
              <CarouselItem key={id} {...item} />
            )}
          </Carousel>
        </Categories>
      }
      <Categories title="Tendencias">
        <Carousel>
          {trends.map((item, id) =>
            <CarouselItem key={id} {...item} />
          )}
        </Carousel>
      </Categories>
      <Categories title="Originales de Platzi Video">
        <Carousel>
          {originals.map((item, id) =>
            <CarouselItem key={id} {...item} />
          )}
        </Carousel>
      </Categories>
    </>
  );```


Tomado de stackOverflow: https://stackoverflow.com/questions/52219852/two-children-with-the-same-key-in-react

olv est谩 ching贸n el reducer uwu

En lo personal me costo mucho entender redux. y les traigo una forma diferente de implementarlo pero igualmente efectiva鈥

  1. En el src creamos una carpeta llamada redux y dentro creamos dos carpetas una llamada reducers y otra store, cada una con su respectivo index.js

  2. En el index de la carpeta redux/store colocamos nuestro initialState de la siguiente forma:

const initialState = {
  userActive: {
	name :"Campeon"
	},
  token: false,
};
export default initialState;

  1. bien, ahora en el index de la carpeta redux/reducers colocamos las acciones que queremos hacer sodre la data del store, como: traer, eliminar, agregar.
const reducer = (state, action) => {
  switch (action.type) {
    case "SET_VALIDATE": {
      return { ...state, token: action.payload };
    }
    case "SET_USER_ACTIVE": {
      return { ...state, userActive: action.payload };
    }
    default: {
      return state;
    }
  }
};
export default reducer;

  1. Bueno ahora lo que hay que hacer es envolver nuestra aplicacion con nuestro store, esto con el fin de que podamos acceder a la data del store desde cualquier componente.
    Entonces vamos a nuestro index.js principal donde tenemos nuestro ReactDOM.render y agregamos lo siguiente:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import reducer from "./redux/reducers";
import initialState from "./redux/store";
import App from "./routes/app";

const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__();
const store = createStore(reducer, initialState, composeEnhancers);

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);

  1. Ya estamos muy cerca, ahora solo tenemos que ir al componente que queremos utilizar la data y traerla con un hook llamado useSelector desde reactr-redux y lo mostramos donde convengamos.
import { useSelector, useDispatch } from "react-redux";
const Header = () => {
  const userActive = useSelector((state) => state.userActive);

  return (
    <div className="HeaderContainer">
        <strong>{userActive.name && userActive.name}</strong>
</div>
  1. y listo, asi de facil, ahora solo nos queda utilizar las acciones que habiamos creado en la carpeta redux/reducers para esto utilizamos un hook llamado useDispatch desde react-redux de la siguiente manera
import { useDispatch } from "react-redux";
const Header = () => {
  const dispatch = useDispatch();;

  return (
    <div className="HeaderContainer">
        <button
          onClick={() => {
            dispatch({
              type: "SET_USER_ACTIVE",
              payload: {},
            });
          }}
        >
         Salir
        </button>
    </div>
  );
};

export default Header;

Te explico como funciona el dispatch: simplemente es una funcion que necesita un objeto con dos datos, el type y el payload. el type es el nombre que utilizamos en el CASE del reducer y el payload es la nueva data.

Ahora te invito a usar useSelector en otro componente diferente y ver si efectivamente la data se modifica.

Bueno eso es todo por ahora, en lo personal esta forma me parece mucho mas sencilla de entender y de implementar. si tienen problemas o dudas me dejan su comentario. Corazon para que no quede en el olvido.

Personalmente este curso no me esta gustando, he regresado varias veces las clases pero no logro entender si quiera que es un reducer y en que me beneficia usar redux, alguien mas se siente asi? o le pasa lo mismo?

recomiendo usar useDispatch y useSelector en vez de connect

Se debe validar que el carrusel que env铆a la acci贸n no sea el de myList (o repetiremos elementos en nuestra lista), para esto podemos agregar un prop al CarouselItem, digamos usable y setearlo por defecto en true, luego en el handleFavorite usamos una condicional, de la siguiente manera:

CarouselItem.js:

...
const CarouselItem = ({
  usable = true,
  id,
  cover,
  title,
  year,
  contentRating,
  duration,
  setFavorite
}) => {
  const handleSetFavorite = () => {
    if (usable) setFavorite({ id, cover, title, year, contentRating, duration })
  }
...

Home:

...
<Carousel>
  {myList.map(item => (
    <CarouselItem key={item.id} {...item} usable={false} />
  ))}
</Carousel>
...

As铆 se ver铆a el Home con el uso del Hooks useSelector de react-redux

import React from 'react';
import { useSelector } from 'react-redux';
import Search from '../components/Search';
import Categories from '../components/Categories';
import Carousel from '../components/Carousel';
import CarouselItem from '../components/CarouselItem';

import '../assets/styles/App.scss';

const Home = () => {
  const { myList, trends, originals } = useSelector(state => state);
  return (
    <>
      <Search />
      {myList.length > 0 && (
        <Categories title="Mi Lista">
          <Carousel>
            {myList.map(item => 
              <CarouselItem key={item.id} {...item} />
            )} 
          </Carousel>
        </Categories>
      )}

      <Categories title="Tendencias">
        <Carousel>
          {trends.map(item => 
            <CarouselItem key={item.id} {...item} />
          )} 
        </Carousel>
      </Categories>

      <Categories title="Originales de Platzi Video">
        <Carousel>
          {originals.map(item => 
            <CarouselItem key={item.id} {...item} />
          )} 
        </Carousel>
      </Categories>

    </>
  );
};

export default Home;

y en CarouselItem podemos hacer uso del Hooks useDispatch, quedando de la siguiente manera:

import React from 'react';
import { useDispatch} from 'react-redux';
import PropTypes from 'prop-types';
import { setFavorite } from '../actions';
import '../assets/styles/components/CarouselItem.scss';
import playIcon from '../assets/static/play-icon.png';
import plusIcon from '../assets/static/plus-icon.png'

const CarouselItem = (props) => {
  const { id, cover, title, year, contentRating, duration } = props;
  const dispatch = useDispatch();

  const handleSetFavorite = () => {
    const payload = { id, cover, title, year, contentRating, duration }
    dispatch(setFavorite(payload))
  }

  return (
    <div className="carousel-item">
      <img className="carousel-item__img" src={cover} alt={title} />
      <div className="carousel-item__details">
        <div>
          <img className="carousel-item__details--img" src={playIcon} alt="Play Icon" />
          <img 
            className="carousel-item__details--img" 
            src={plusIcon}
            alt="Plus Icon"
            onClick={handleSetFavorite}
          />
        </div>
        <p className="carousel-item__details--title">{title}</p>
        <p className="carousel-item__details--subtitle">{`${year} ${contentRating} ${duration}`}</p>
      </div>
    </div>
  )
};

CarouselItem.propTypes = {
  title: PropTypes.string,
  year: PropTypes.number,
  contentRating: PropTypes.string,
  duration: PropTypes.number,
  cover: PropTypes.string,
};

export default CarouselItem;

Algo que acabo de notar, es que si recargan el navegador la lista pierde la informaci贸n

Dejo este enlace de video que me ayudo a comprender un poco mejor el funcionamiento de REDUX.
https://www.youtube.com/watch?v=5iMhFH9alI0

Este tema hay que tomarlo con pinzas y lupa de relojero 馃攳

Fue toda una odisea este tema de redux, como todos al principio pas茅 este curso solamente confiando ciegamente en el profesor y sin saber lo que estaba haciendo. Se me hizo tan dif铆cil de entender que simplemente lo dej茅 de lado.

A mi parecer en toda esta escuela de JS abordaron demasiado r谩pido y un poco superficial estos temas de los hooks, router y redux. A mi gusto explican todo demasiado r谩pido que hasta se me lagguea el cerebro tratando de encontrar una explicaci贸n l贸gica y no simplemente verlo todo como 鈥渕agia鈥.

Mi recomendaci贸n es que no se frustren en tratar de entenderlo a la primera, en vez de eso vayan a buscar como se trabaja con el state de cada componente por separado. Practiquen mucho simplemente con el state y el useState (a煤n no s茅 como usar useEffect) y ya despu茅s se van a dar cuenta que van a necesitar si o s铆 una forma de manejar una sola informaci贸n para toda su aplicaci贸n en vez de estar repitiendo los datos en cada componente. Es ah铆 cuando vuelven a repasar estas clases y ahora todo va a tener sentido.

Tambi茅n lo que he visto mucho en estos cursos es que trabajan demasiado los componentes como funciones o arrow functions y no tanto como clases. Yo me rehusaba a usarlos, pero la verdad me siento m谩s c贸modo ahora que los empleo todos como clases y no simples funciones (claro hay veces que es innecesario, pero en su mayor铆a todo lo manejo con clases).

De igual manera esta es mi opini贸n meramente personal, nunca he sido bueno para aplicar y relacionar las cosas con la simple teor铆a. Siempre he sido m谩s de estar a prueba y error, eventualmente termino entendiendo todo y aunque sienta que voy demasiado lento eventualmente todos llegamos a donde mismo.

P.D: Una cosa que me ayud贸 bastante tambi茅n es haber empezado a usar React Bootstrap, ya que aqu铆 los componentes interactivos como modals, navbar y formularios se manejan mucho con la manipulaci贸n de los estados.

Me costo mucho hacer la destructuraci贸n del objeto ya que mis listas est谩n dentro de un objeto categories, pero al fin lo consegu铆 :3

me queda algo as铆:

case 'SET_FAVORITE':
      return {
        ...state,
        categories: {
          ...state.categories,
          myList: [...state.categories.myList, action.payLoad],
        },
      };

Es de esta forma entonces que se pueden actualizar datos dentro de atributos de un objeto 馃槂

Una forma para evitar que agregue duplicados podr铆a ser

case 'SET_FAVORITE':
            const result = state.myList.filter(item => item.id === action.payload.id);
            return result.length > 0 ? state : {
                ...state,
                myList: [...state.myList, action.payload]
            }

En el reducer en vez de usar un switch no es mejor usar un 鈥渋f else鈥 son solo dos casos鈥

Yo desconozco donde emplear la l贸gica para realizar validaciones, pero desde mi punto de vista los componentes no deber铆an tener dicha l贸gica, por lo que hice la validaci贸n de no agregar duplicados en el reducer:

case 'SET_FAVORITE':
      if (state.myList.some((item) => item.id === action.payload.id)) {
        return {
          ...state,
        };
      }
      return {
        ...state,
        myList: [...state.myList, action.payload],
      };

Tengo un problema, escribo todo el codigo bien, pero no me agrega los CarouselItems a la seccion de myList, no me arroja ningun error ni nada, simplemente no funciona, tengo el codigo exactamente igual que el profesor en la clase, he revisado muy bien el codigo pero no encuentro el motivo de por que no funciona, por favor si alguien me puede ayudar, se lo agradeceria

Shift + Alt + F ordena el c贸digo y ahorra muuucho tiempo

Configuraci贸n de Carousel Item

Creaci贸n del archivo reducer

Para manejar el flujo de informacion de la aplicacion, vamos a trabajar los Actions y los reducers. En este caso en el de agregar a la lista. vamos a ver los actions que en nuestro index vamos a crear el primer funcion que vamos a escribir la accion que vamos a hacer y pasar un objeto que tendremos disponible dentro del reducer, el cual va a tomar la accion que estamos realizando para guardar la accion en el estado.

export const setFavorite = payload => ({
    type: 'SET_FAVORITE',
    payload,
})

Ahora el reducer se va a encargar de entender que es lo que esta pasando y como actualizara el estado. Crearemos un switch que nos permite recibir el type, evaluarlo con un caso y saber que haremos con el estado.

const reducer = (state, action) => {
    
    switch (action.type) {
        case 'SET_FAVORITE':
            return {
                ...state,
                mylist: [...state.mylist, action.payload]    
            }
            break;
    
        default:
            return state;
    }

}
export default reducer;

Ahora solo actualizaremos nuestro componente de Carousel Item que ya sabemos que tenemos que conectar nuestra aplicaicon. Aqui vamos a mandarle nulo ya uqe no vamos a mapear los estados, el otro es MapDispatchToProps. Otra cosa es agregar la constante de mapDispatchToProps a la cual le daremos la funcion de setFavorite y lo importamos de los actions:

const mapDispatchToProps = {
  setFavorite, 
}

export default connect(null, mapDispatchToProps)(CarouselItem)

Ahora modificaremos nuestro componente para que tenga un retorno explicito para poder agregarle logica. Ahora mandaremos los props de forma deconstruida.

const { cover, title, year, contentRating, duration } = props;

Ahora crearemos nuestra funcion que hara la parte de agregar los elementos, a la cual solo le diremos que en props.setFavorite mandarle el objeto con los valores de nuestro ITEM para que lo agregue a mi lista

const handleSetFavorite = () => {
    props.setFavorite({
      cover, title, year, contentRating, duration,
    })
  }

Por si alguien tiene algun error con el render de su Lista

        {myList.length > 0 &&
            <Categories title="Mi lista">
                <Carousel>
                    {
                        myList.map(item =>
                            <CarouselItem key={item.id} {...item} />
                        )
                    }
                </Carousel>
        </Categories>
        }

Permiso me gustar铆a aclarar que Favorito en ingl茅s se escribe, Favourite y se pronuncia algo as铆 c贸mo (leer literal en espa帽ol)= FEIVRIT 鈥 馃榿

M谩s de una hora mirando el por qu茅 no me agregaba los valores a la lista de mylist y era por que en el objeto de mapStateToProps del container Home ten铆as state.myList y en el data estaba como 鈥渕ylist鈥

Wow, me vi el curso de react hooks, y viendo como funciona el useReducer (que me costo infiernos entenderlo), ahora entiendo m谩s f谩cil redux, y si ustedes aun no lo logran, no se rindan, todo el mundo lo sabr铆a si fuera tan f谩cil como una suma !

Recomiendo este par de videos para entender mejor Redux:

video1
Video2

Yo antes de aprender redux hice aplicaciones simples pero bien elaboradas usando bases de datos reales, y eso me ayudo en realidad a comprender el flujo completo, me parece que es mejor saber un poco de backend para poder implementar redux de una forma mas clara.

Tengo una duda y espero que me puedan ayudar, entiendo que se crea una funci贸n en el CarouselItem.jsx, dicha funci贸n trae el action y le pasa como par谩metro (payload) los props que trae el item, al mismo tiempo el reducer mediante el switch selecciona el type y hace alguna cosa, en este caso mantener el state, y los items que ya tenga el array myList, para agregar lo que payload traiga (si me estoy equivocando en algo, d铆ganme porfa :v), lo que no entiendo, es c贸mo demonios es que se agrega el componente completo si s贸lo le estamos pasando props. Quiz谩 sea muy absurda o muy evidente la respuesta, pero no logro comprender !!, mil gracias !

Hoy con ayuda de los hooks en React, creo que puede ser m谩s f谩cil su compresi贸n.

Dejo aqu铆 esto para que les sirvan de ayuda:

https://react-redux.js.org/api/hooks

Un action de Redux va a contener dos elementos:

type: para indicar la acci贸n que se va a ejecutar.
payload: es la informaci贸n que estamos mandando al reducer.

Dentro de los reducers usaremos un switch para separar la l贸gica por cada tipo de acci贸n que tendremos en Redux.

Realmente se aprende de los errores.

Al finalizar la tarea nada me funcionaba y me toco investigar m谩s a fondo para entender que estaba haciendo mal, al final tenia un **return {} ** donde deb铆a estar un return () , pero aprend铆 mucho de redux en el proceso.

Gracias benditos Bugs鈥 jejjeje

Explicaci贸n del m茅todo connect

duda, redux guarda el estado en el localStorage??

y cuando le introdujimos alguna informacion a payload?

no me agrega al pulsar el boton me sale un error!

porque le el swith no se utiliza el breack?

Por favor alguien podria explicarme bien la desestructuracion "鈥"
Entiendo su funcion de traer todos los elementos del state a un bloque de codigo , pero hasta ahi nomas no lo entiendo en profundidad!

Desde ya muchas gracias!!

me sirve cuando agrego pero me sale el siguiente error,

porque no se uso el hook useSelector? o es que a la salida de este curso el hook no existia?

No me dejaba guardar m谩s de un elemento, encontre dando console.log en el reducer, que no llevaba el ID. Asi que por si les pasa los mismo, deber铆an agregarlo a las props del carouselItem.

const CarouselItem = (props) => {
  const { id, cover, title, year, contentRating, duration } = props

  const handleSetFavorite = () => {
    props.setFavorite({
      id, cover, title, year, contentRating, duration,
    })
  }
  return (
    <div className='carousel-item'>
      <img className='carousel-item__img' src={cover} alt='' />
      <div className='carousel-item__details'>
        <div>
          <img
            className='carousel-item__details--img'
            src={playIcon}
            alt='Play Icon'
          />
          <img
            className='carousel-item__details--img'
            src={plusIcon}
            alt='Plus Icon'
            onClick={handleSetFavorite}
          />
        </div>
        <p className='carousel-item__details--title'>{title}</p>
        <p className='carousel-item__details--subtitle'>
          {`${year} ${contentRating} ${duration}`}
        </p>
      </div>
    </div>
  )
}

驴De donde sale action.type?

Encontre esta lista de reproduccion en youtube para el que le sirva para entender mejor los conceptos de redux https://www.youtube.com/watch?v=5iMhFH9alI0&list=PL4WxketMZHyeeU3pilSJbgiIFnVzSUFVb&ab_channel=JuanJoseOrtiz

export const setFavorite = (payload) => ({
  type: "SET_FAVORITE",
  payload,
});

Me da este error, segui todos los pasos

Vaya ando un poco confundido no lo voy a negar, leyendo los comentarios y los links que dan de apoyo los compa帽eros comprendo un poco mas, pero creo que debo practicar bastante para lograr entender a profuncidad bien esto de Redux

Creo que el t茅rmino no es 鈥渄estructurar el estado鈥, porque eso hace referencia a la extracci贸n de los datos de este mismo, sino m谩s bien 鈥渆sparcir鈥, pues al fin y al cabo lo est谩 haciendo con el 鈥渟pread operator鈥, 煤 鈥渙perador de esparcimiento鈥 definido por los tres puntos 鈥溾︹.
S茅 que esto no har谩 que la aplicaci贸n funcione diferente, pero a nivel de conceptos se me hace que tiene m谩s sentido as铆.

De acuerdo a la documentaci贸n de airbnb, resulta mejor hacer el destructuring de los datos como lo ten铆amos anteriormente, y no sacando las variables desde los props que se reciben.

si hubiera entendido Redux de hace a帽os de esta manera, gracias por este gran curso

Ac谩 les comparto un diagrama de Redux, para ayudar a comprender un poco m谩s la explicaci贸n del profesor.

Como dato curioso por si alguien m谩s se lo pregunt贸 en el minuto 1:40 cuando configura el type del action y dice que lo haremos con snake case, se refiere a una pr谩ctica al asignar valores en el cual se separan las palabras con Under Score (_) en vez de espacio Ej: SNAKE_CASE

Esta clase estuvo genial! Cada vez amo m谩s a React 鉂わ笍

Alguna idea de por qu茅 me aparece este error:

Esto es lo que tengo en Home.js:

import React from 'react';
import { connect } from 'react-redux';
import Search from '../components/Search';
import Categories from '../components/Categories';
import Carousel from '../components/Carousel';
import CarouselItem from '../components/CarouselItem';
import '../assets/css/App.scss';

const Home = ({ myList, trends, originals }) => {
  return (
    <>
      <Search />
      {
        myList.length > 0 && (
          <Categories title='Mi Lista'>
            <Carousel>
              {
                myList.map((item) => (
                  <CarouselItem key={item.id} {...item} />
                ))
              }
            </Carousel>
          </Categories>
        )
      }
      <Categories title='Tendencias'>
        <Carousel>
          {
            trends.map((item) => (
              <CarouselItem key={item.id} {...item} />
            ))
          }
        </Carousel>
      </Categories>
      <Categories title='Originales'>
        <Carousel>
          {
            originals.map((item) => (
              <CarouselItem key={item.id} {...item} />
            ))
          }
        </Carousel>
      </Categories>

    </>
  );
};

const mapStateToProps = state => {
  return {
    myList: state.myList,
    trends: state.trends,
    originals: state.originals,
  };
};

export default connect(mapStateToProps, null)(Home);

En la vista CarouselItem hay un peque帽o bug y es que no env铆a un id en setFavorite por lo que en el Home se esta creando items con key undefined para solucionar el warning solo es pasar el id del props al setFavorite

const CarouselItem = ({ id, cover, title, year, contentRating, duration, setFavorite }) => {
  const handleSetFavorite = () => {
    setFavorite({
      id, cover, title, year, contentRating, duration
    });
  }
  return (
    <div className="carousel-item">
      <img className="carousel-item__img" src={cover} alt={title} />
      <div className="carousel-item__details">
        <div>
          <img className="carousel-item__details--img" src={playIcon} alt="Play Icon" />
          <img className="carousel-item__details--img" src={plusIcon} alt="Plus Icon" onClick={handleSetFavorite} />
        </div>
        <p className="carousel-item__details--title">{title}</p>
        <p className="carousel-item__details--subtitle">
          {`${year} ${contentRating} ${duration}`}
        </p>
      </div>
    </div>
  );
};```

Cuando se usa mapStateToProps & mapDispatchToProps ?

parece magia esto, xD

Dos dias revisando el c贸digo y tenia mal escrito SET_FAVORITE
XD

Alguien sabe porque ocurre este error, es al momento de hacer click en el icono de plus

T铆o yo s铆 hab铆a pensado, esa funci贸n en actions est谩 muy raraaaaa

El action le pasa al reducer una acci贸n que debe ejecutar y un payload, y el reducer es el encargado de saber como va a modificar (o no) el estado en funci贸n de la acci贸n y el payload entregados por el reducer.
En la doc. dice

鈥減uedes pensar en un action como un evento que describe algo que sucede en la aplicaci贸n鈥

Y dice de un reducer
"Puedes pensar en un reducer ccomo un event listener el cual maneja los eventos con base en el action que recibe(evento) type (y el payload)

b

Este esquema (aproximado), muestra las partes dentro de cada compoente para recordar estos import o funciones importantes

Pr谩ctica:

Se puede usar el shorcut para formatear el codigo alt+shit+f