Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

3 formas de crear un reducer

13/19
Recursos

Aportes 15

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Así como lo estás diciendo, está bien, Juan.
Los corchetes son estos:
[ ] => Los que utilizamos para los arreglos.
Y estas son las llaves:
{ } => Las que utilizamos para los objetos.

Por cierto, es la primera vez que me queda tan claro el reducer. De verdad, gracias. 💚

3 formas de crear un reducer
Usando condicionales if:

const reducerIF = (state, action) => {
   if (action.type === 'ERROR') {
       return {
           ...state,
           error: true,
           loading: false,
       }
   } else if (action.type === 'CONFIRM') {
       return {
           ...state,
           error: false,
           loading: false,
           confirmed: true,
       }
   } else {
       return {
           ...state,
       }
   }
}

Usando switch case:

const reducerSWITCH = (state, action) => {
   switch (action.type) {
       case 'ERROR':
           return {
               ...state,
               error: true,
               loading: false,
           };
       case 'CONFIRM':
           return {
               ...state,
               error: false,
               loading: false,
               confirmed: true,
           };
       default:
           return {
               ...state,
           };
   }
}

Usando objetos:

const reducerOBJECT = (state) => ({
   'ERROR': {
       ...state,
       error: true,
       loading: false,
   },
   'CONFIRM': {
       ...state,
       error: false,
       loading: false,
       confirmed: true,
   },
})
 
const reducer = (state, action) => {
   if (reducerOBJECT(state)[action.type]) {
       return reducerOBJECT(state)[action.type];
   } else {
       return {
           ...state,
       }
   }
}

La funcion para manejar nuestro reducerObject es:

const reducer = (state, action) => {
  if (reducerObject(state)[action.type]) {
    return reducerObject(state)[action.type];
  } else {
    return state;
  }
};

La podemos simplificar para hacerla mucho mas elegante y facil de leer de la siguiente manera:

const reducer = (state, action) => {
  return (reducerObject(state)[action.type] || state);
};

Hay otra forma que es una variación de la tercera:

const reducerObject = {
    'ERROR': {
        error: true,
        loaidng: false
    },
    'CHECK': {
        loading: true
    }
}
function reducerForState(reducerObject) {
    return function reducer(state, action) {
        return {...state, ...reducerObject[action.type] }    
    }
}

export const reducer = reducerForState(reducerObject)

donde reducerForState es una HOF que se puede reusar para distintos reducers

y si usan typescript

interface Action<ReducerObject> {
    type: keyof ReducerObject
}
const reducerObject = {
    'ERROR': {
        error: true,
        loading: false
    },
    'CHECK': {
        loading: true
    }
}
function reducerForState<T>(reducerObject: T) {
    return function reducer<State>(state: State, action: Action<T>): State {
        return {...state, ...reducerObject[action.type] }    
    }
}
export const reducer = reducerForState(reducerObject)

( ), [ ], { }
Paréntesis, corchetes y llaves así lo aprendí en la secundaria😎

A mi parecer queda re bonito con el if ternario.

const reducer = (state,action) => {
  (reducerObject(state)[action.type]) 
    ? reducerObject(state)[action.type]
    : state
}

Gran curso Juan! estoy con ganas de ver ese que se viene de Redux 👀

La del if no me gusta, la del switch me parece la mejor simplemente porque es muy fácil de entender y la de los objetos me parece la mejor en elegancia pero si es un poquiiito más compleja de entender a simple vista.

La razón por la que el return dentro del switch es más que suficiente, es porque solo puede haber un return por cada función, y esto nos ayuda a evitar que se ejecute el código que va después del return.
.
"¿Pero cómo? ¡Si yo tengo más de un return dentro de mi código y no me marca error!" Si. Pero el hecho de que tengas más de un return dentro de tu función no significa que se ejecuten todos. Ejemplo:

function ejemploSimple() {
	return 'Hola mundo!'
	return 'Adios mundo!'
}

ejemploSimple() // 'Hola mundo!'

En la función anterior, a pesar de haber más de un return, solo se ejecutará el primero. Después de eso, la función dejará de leer lo que este escrito después de ese primer return que se encontró.
.
Ahora, ¿esto quiere decir que siempre se ejecutará el primer return que esté escrito? Pues no necesariamente. Veamos el siguiente ejemplo:

function segundoEjemplo(number) {
	if(number > 10) {
		return 'Es mayor a 10'
	}
	if(number < 10) {
		return 'Es menor a 10'
	}
	return 'Es igual a 10'
}

segundoEjemplo(20) // 'Es mayor a 10'
segundoEjemplo(5) // 'Es menor a 10'
segundoEjemplo(10) // 'Es igual a 10'

En el caso anterior, al ejecutar nuestra función de la siguiente manera segundoEjemplo(20), esto hará que nuestro código ejecute el segundo return, no el primero. O en caso de que ejecutemos la función de la siguiente manera segundoEjemplo(10), hará que se ejecute el tercer return, no los dos primeros.
.
La ventaja que tienen los return, es que al momento de que nuestro código se encuentre con uno de ellos dentro de una función, éste dejará de leer lo que viene escrito después de ese return y la función solo devolverá el valor que el return indicaba. Esto a diferencia de los break dentro de los switch, ya que los break solo se encargan de parar la ejecución del bloque switch, no de la función completa. Por ejemplo:

let respuesta = ''

function primerSwitch(number) {
	let numerito = ''
	switch(number) {
		case 10:
			numerito = 'el numero es 10'
			break;
		case 20:
			numerito = 'el numero es 20'
			break;
	}
	respuesta = 'la respuesta se sobreescribio'
	return numerito
}

primerSwitch(10) // el numero es 10
respuesta // 'la respuesta se sobreescribio'

En el código anterior, al usar el break dentro de nuestro switch, nos ayuda a que solo devuelva uno de los dos casos provistos. Pero esto no impide que se siga ejecutando lo que esta dentro de la función una vez que acaba el switch, ya que si ejecutamos la función podemos ver que la variable respuesta se sobreescribe. En cambio, esto sería diferente si usáramos un return dentro del switch. Ejemplo:

let respuesta = ''

function segundoSwitch(number) {
	switch(number) {
		case 10:
			return 'el numero es 10'
		case 20:
			return 'el numero es 20'
	}
	respuesta = 'ahora la variable no se sobreescribe'
}

segundoSwitch(10) // 'el numero es 10'
respuesta // ''

En este caso, la ejecución de la función acaba donde encuentra el primer return, lo que hace que el código enseguida del switch no se ejecute.
.
Puede ser algo básico para algunas personas, pero espero le haya sido de utilidad por lo menos a alguien de ustedes 😃

###Mi practica

const initialState = {
    value: "",
    error: false,
    loading: false,
    deleted: false,
    confirmed: false
};
//Base
/*
const reducer = (state, action) => {

}*/
const reducerIf = (state, action) => {
    if (action.type === "ERROR") {
        return {
            ...state,
            error: true,
            loading: false
        };
    } else if (action.type === "CHECK") {
        return {
            ...state,
            loading: true
        };
    } else {
        return {
            ...state
        }
    }
}
const reducerSwitch = (state, action) => {
    switch (action.type) {
        case 'ERROR':
            return {
                ...state,
                error: true,
                loading: false
            };
        case "CHECK":
            return {
                ...state,
                loading: true
            };
        default:
            return {
                ...state
            };
    }
}

const reducerObject = (state) => ({
    'ERROR': {
        ...state,
        error: true,
        loading: false
    },
    "CHECK": {
        ...state,
        loading: true
    }
});
const reducer = (state, action) => {
    if(reducerObject(state)[action.type]){
        return reducerObject(state)[action.type]
    }else{
        return state;
    }
}

Tres formas de crear un reducer

const initialState = {
  confirmed: false,
  deleted: false,
  value: '',
  error: false,
  loading: false,
};


// Base Way 
const reducer1 = (state, action) => {

};


const reducerIf = (state, action) => {
  if (action.type === 'ERROR'){
    return {
      ...state,
      error: true,
      loading: false,
    }; 
  } else {
    return {
     ...state,  
    }
  }
};


const reducerSwitch = (state, action) => {
  switch(action.type){
    case 'ERROR':
      return {
        ...state,
        error: true,
        loading: false,
      };
    default:
      return {
        ...state,
      }
  }
};

// Reducer Object
const reducerObject = (state) => ({
  'ERROR': {
    ...state,
    error: true,
    loading: true,
  }
});

const reducer = (state, action) => {
  if(reducerObject(state)[action.type]) {
    reducerObject(state)[action.type];
  } else {
    return state;
  }
};

Llevo trabajando en React 2 años y medio y esta es la primera vez que entiendo a la perfección los reducers.

gracias juan David Castro

A mi preferencia me gustó mucho mas hacer los reducers con Switch

¿A ustedes de qué forma les gustó más?

Me gusto mucho la ultima forma de hacer reducer, pero quedaria un poquito mas elegante así:

const reducer = (state, action) => 
reducerObject(state)?.[action.type] || state

Coincido que el objeto es mas elegante

El uso de objetos para el reducer es excelente cuando hay una asignación de estados simples, es decir, cuando tu dispatch solo sobreescribe valores o agrega elementos a un array, pero con otros approach, cuando tienes que hacer un flujo más complejo, como agregar elementos no repetidos a un array se complica bastante el uso de un reducerObject, así que el uso de este approach u otros siempre dependerá de tus necesidades.