No tienes acceso a esta clase

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

Action creators y actionTypes

15/19
Recursos

Aportes 36

Preguntas 2

Ordenar por:

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

o inicia sesi贸n.

Jah, el profe no me gano, puse pausa al video y termine primero !

Action Types: consiste en usar un objeto para almacenar las keys de nuestro reducer:

const actionTypes = {
   error: 'ERROR',
   confirm: 'CONFIRM',
}

Action Creators: consiste en declarar funciones que contienen nuestros dispatch:

const onError = () => dispatch({ type: actionTypes.error });
 
const onWrite = ({ target: { value } }) => {
    dispatch({ type: actionTypes.write, payload: value });
}

Min 11:26
No es que el lenguaje le ponga los parentesis, sino que le estamos dando una referencia de esa variable, cuando JS va a la variable se da cuenta que es una funcion, y la ejecuta. 鉁

Mi mam谩 ortografica estar谩 fudiosa 馃ぃ

Le agregue la propiedad de disabled al input ya que me parec铆a algo raro que podamos seguir escribiendo cuando el loading esta en true.

<input
               disabled={state.loading}
               placeholder="Codigo de seguridad"
               value={state.value}
               onChange={onWrite}
/>

As铆 cuando loading sea true, disabled ser谩 true y viceversa.

actionTypes

  • Cuando llamamos a dispath debemos darle un valor a action.type.
  • Con el uso de actionTypes podremos evitar los errores de tipeo.
  • consiste en usar un objeto para almacenar las keys de nuestro reducer

Action creators:

  • Son funciones para actualizar el estado
  • Consiste en declarar funciones que contienen nuestros dispatch

Ese momento donde agradeces tener GitHub Copilot y le ganas al profe xd, tal vez hice un poco de trampa jajaja

Agregue algunos estilos b谩sicos鈥
.

Me volvi贸 a pasar lo mismo que con los otros cursos de este profesor, aunque considero que explica muy bien y sabe mucho;
te marea demasiado cuando va borrando y cambiando tanto el c贸digo. Tal vez est谩 bueno que se explique de una como ser铆a, o buscar otro m茅todo de explicar los conceptos. Realmente es bastante confusa esta manera de explicar.

Usando actionTypes con switch/case:

import React, { useEffect, useReducer, Fragment } from 'react'

const SECURITY_CODE = 'paradigma'

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

const actionTypes = {
	error: 'Error',
	confirm: 'Confirm',
	write: 'Write',
	check: 'Check',
	delete: 'Delete',
	reset: 'Reset',
}

const reducer = (state, action) => {
	switch (action.type) {
		case actionTypes.error :
			return {
				...state,
				error: true,
				loading: false,
			}
		case actionTypes.confirm :
			return {
				...state,
				loading: false,
				error: false,
				confirmed: true,
			}
		case actionTypes.write :
			return {
				...state,
				value: action.payload,
			}
		case actionTypes.check :
			return {
				...state,
				loading: true,
				error: false,
			}
		case actionTypes.delete :
			return {
				...state,
				deleted: true,
			}
		case actionTypes.reset :
			return {
				...state,
				value: '',
				confirmed: false,
				deleted: false,
			}
		default:
			return {
				...state,
			}
	}
}

export default function UseReducer() {
	const [ state, dispatch ] = useReducer(reducer, initialState)

	useEffect(
		() => {
			if (state.loading) {
				setTimeout(() => {
					if (state.value === SECURITY_CODE) {
						dispatch({ type: actionTypes.confirm })
					} else {
						dispatch({ type: actionTypes.error })
					}
				}, 1000)
			}
		},
		[ state.loading ]
	)

	if (!state.deleted && !state.confirmed) {
		return (
			<div>
				<h2>Eliminar UseReducer</h2>
				<p>Por favor, escriba el c贸digo de seguridad.</p>
				{state.loading ? 'Cargando...' : state.error ? 'Error :(' : null}
				<br />
				<input
					type='text'
					placeholder='c贸digo de seguridad'
					value={state.value}
					onChange={ev => dispatch({ type: actionTypes.write, payload: ev.target.value })}
				/>
				<button onClick={() => dispatch({ type: actionTypes.check })}>Comprobar</button>
			</div>
		)
	} else if (!state.deleted && state.confirmed) {
		return (
			<Fragment>
				<p>Pedimos confirmaci贸n. 驴Tas seguro?</p>
				<button onClick={() => dispatch({ type: actionTypes.delete })}>Si, eliminar</button>
				<button onClick={() => dispatch({ type: actionTypes.reset })}>No, me arrepent铆</button>
			</Fragment>
		)
	} else {
		return (
			<Fragment>
				<p>Eliminado con 茅xito</p>
				<button onClick={() => dispatch({ type: actionTypes.reset })}>Regresar</button>
			</Fragment>
		)
	}
}

Creer铆a que la parte de Action Types no ser铆a necesaria si utilizamos Typescript para React. Ya que expl铆citamente puedo declararle los tipos que puede soportar la key 鈥渢ype鈥 de la siguiente forma:

type Action ={
type: 鈥榃RITE鈥 | 鈥楥ONFIRM鈥 | 鈥楨RROR鈥 | 鈥楧ELETE鈥 | 鈥楥HECK鈥 | 鈥楻ESET鈥,
payload?: string,
}

Entonces si me llego a equivocar, TS autom谩ticamente lo detecta y me arroja el error.

Yo pase el argumento de onWrite de la siguiente manera :

        <input 
          placeholder="C贸digo de Seguridad" 
          value={state.value} 
          onChange={e => {
            onWrite(e.target.value)
        }}/>

y en el action creator

  const onWrite = (newValue) => {
    setState({
      ...state,
      value: newValue
    })
  } 

Este es el resultado final de el proyecto trabajado en este curso

No se hasta que punto conviene hacer el codigo tan declarativo鈥 lo cuestiono mucho

por que se complica tanto ??? me parece innesesario e.e

con TypeScript podemos evitar los errores ortograficos, utilizando type o interfaces

type State = {
    error: boolean,
    loading: boolean,
    value: string,
    deleted: boolean,
    confirmed: boolean
}

type Action = {
    type: "CHECK" | "ERROR" | "CONFIRM" | "WRITE" | "DELETED" | "RESET",
    payload?: string
}

const reducerObject = <T,>(state: T, payload = "") => ({
    CONFIRM: {
        ...state,
        error: false,
        loading: false,
        confirmed: true
    },
    ERROR: {
        ...state,
        error: true,
        loading: false
    },
    CHECK: { 
        ...state,
        loading: true
    },
    WRITE: {
        ...state,
        value: payload
    },
    DELETED: {
        ...state,
        deleted: true
    },
    RESET: {
        ...state,
        confirmed: false,
        deleted: false,
        value: ""
    }
})

const reducer = (state: State, action: Action): State => {
    return reducerObject(state, action.payload)[action.type]
}

Sintaxis para asignar el valor de una variable como llave de un objeto:

const username = "juan"

const obj = {
	[username]: "hernandez"
}

console.log(obj.juan) //hernandez

Link

Lo que mas me gusto de esta clase fue la forma en la que utilizamos el actionTypes que si uno quisiera con typescript podria usarlo como un enum y listo ya no mas switches

Super 煤til, gracias!

Me recuerda a los enums en Kotlin

Si bien en el onChange se resumia en cuanto a la legibilidad aconsejo que se haga de siguiente, en resumen quedarnos con la anterior version, esto ya que cuando se intenta dar soporte a proyectos grandes estos necesitan tal cual ser 鈥榝aciles de leer鈥

  • Por cierto si hablamos en terminos de la complejidad que pueda tener la redundancia, se podria decir que simplemente llega a ser
          onChange={(event) => onWrite(event.target.value)} 

Complexity(lineal), si me equivoco me corrigen por favor:

  const dun = (event.target.value) => (value) => {
    dispatch({ type: actionTypes.write, payload: value})
  };

Fuente: https://www.cs.us.es/~jalonso/cursos/i1m-19/temas/tema-28.html

Usar types en typescript o interface para el tipado es otra alternativa para este caso.

Action Creators

Incluso podemos crear un archivo propio para los actionTypes:

export const ACTION_TYPES = {
  CHECK: 'CHECK',
  CONFIRM: 'CONFIRM',
  DELETE: 'DELETE',
  ERROR: 'ERROR',
  RESET: 'RESET',
  WRITE: 'WRITE',
}

Ya despu茅s lo mandamos a llamar en el archivo que lo necesitemos:

import { useReducer, useEffect, useCallback } from 'react'
import { ACTION_TYPES } from './actionTypes'
import './UseState.css'

const SECURITY_CODE = 'techzone'

function UseReducer({name}) {
  const [state, dispatch] = useReducer(reducer, initialState)

  const onCheck = () => dispatch({ type: ACTION_TYPES.CHECK })

  const onConfirm = () => dispatch({ type: ACTION_TYPES.CONFIRM })

  const onDelete = () => dispatch({ type: ACTION_TYPES.DELETE })

  const onError = () => dispatch({ type: ACTION_TYPES.ERROR })

  const onReset = () => dispatch({ type: ACTION_TYPES.RESET })

  const onWrite = ({target: { value }}) => dispatch({ type: ACTION_TYPES.WRITE, payload: value })

  const changeState = useCallback(() => {
    if (state.loading) {
      setTimeout(() => {
        state.value === SECURITY_CODE ? onConfirm() : onError()
      }, 2000)
    }
  }, [state])

  useEffect(() => {
    changeState()
  }, [changeState])

  if (!state.deleted && !state.confirmed) {
    return (
      <div>
        <h2>Eliminar {name}</h2>
        <p>Por favor escribe el c贸digo de seguridad</p>

        { state.error && (<p>Error: el c贸digo es incorrecto</p>) }

        { state.loading && (<p>Loading...</p>) }

        <input
          type="text"
          placeholder="C贸digo de seguridad"
          value={state.value}
          onChange={onWrite}
        />
        <button onClick={onCheck}
        >
          Comprobar
        </button>
      </div>
    )
  } else if (state.confirmed && !state.deleted) {
    return (
      <>
        <p>
          Advertencia 鈿狅笍, 驴Est谩s seguro de querer eliminar esto?
          <span className='red'>
            Es irrecuperable
          </span>
        </p>
        <button onClick={onDelete}>
          S铆, eliminar
        </button>

        <button onClick={onReset}>
          No, me arrepent铆
        </button>
      </>
    )
  } else {
    return (
      <>
        <p>Eliminado con 茅xito</p>
        <button onClick={onReset}>
          Resetear
        </button>
      </>
    )
  }
}

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

const reducerObject = (state, payload) => ({
  [ACTION_TYPES.WRITE]: {
    ...state,
    value: payload
  },

  [ACTION_TYPES.CONFIRM]: {
    ...state,
    error: false,
    confirmed: true,
    loading: false
  },

  [ACTION_TYPES.ERROR]: {
    ...state,
    error: true,
    loading: false
  },

  [ACTION_TYPES.CHECK]: {
    ...state,
    loading: true,
  },

  [ACTION_TYPES.DELETE]: {
    ...state,
    deleted: true
  },

  [ACTION_TYPES.RESET]: {
    ...state,
    confirmed: false,
    deleted: false,
    value: ''
  }
})

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

export { UseReducer }

Mi Practica

```jsx
importReactfrom "react";

const SECURITY_CODE = "paradigma";

function UseReducer({name}) {
    const [state, dispatch] =React.useReducer(reducer, initialState);
    const onConfirm = () => {
        dispatch({type: actionTypes.confirm});
    }
    const onError = () => {
        dispatch({type: actionTypes.error});
    }
    const onWrite = (eventValue) => {
        dispatch({type: actionTypes.write, payload:eventValue});
    }
    const onCheck = () => {
        dispatch({type: actionTypes.check});
    }
    const onDelete = () => {
        dispatch({type: actionTypes.delete});
    }
    const onReset = () => {
        dispatch({type: actionTypes.reset});
    }
React.useEffect(() => {

        if (!!state.loading) {
            setTimeout(() => {
                if (state.value === SECURITY_CODE) {
                    onConfirm()
                } else {
                    onError()
                }

            }, 3000);
        }
    }, [state.loading]);
    if (!state.deleted && !state.confirmed) {
        return (
            <React.Fragment>
                <h2>Eliminar{name}</h2>
                <p>Por favor, escribe el c贸digo de seguridad</p>
                {(!state.loading && state.error) && (
                    <p>El C贸digo es incorrecto</p>
                )}
                {state.loading && (
                    <p>Cargando...</p>
                )}
                <input
                    value={state.value}
                    onChange={(event) => {
                        onWrite(event.target.value)
                    }}

                    placeholder="C贸digo de Seguridad"
                />
                <button
                    onClick={onCheck}
                >Comprobar
</button>
            </React.Fragment>
        );
    } else if (!!state.confirmed && !state.deleted) {
        return (
            <React.Fragment>
                <h2>Eliminar{name}</h2>
                <p>驴Seguro que quieres eliminar{name}?</p>
                <button type="button" onClick={onDelete}>Si, eliminar
</button>
                <button type="button" onClick={onReset}>No, cancelar
</button>
            </React.Fragment>
        );
    } else {
        return (
            <React.Fragment>
                <h2>隆{name}eliminado!</h2>
                <button type="button" onClick={onReset}>Recuperar{name}</button>
            </React.Fragment>
        );
    }
}

const initialState = {
    value: "",
    error: false,
    loading: false,
    deleted: false,
    confirmed: false
};
const actionTypes = {
    confirm: 'CONFIRM',
    error: 'ERROR',
    write: 'WRITE',
    check: 'CHECK',
    delete: 'DELETE',
    reset: 'RESET',
}
const reducerObject = (state,payload= false) => ({
    [actionTypes.confirm]: {
        ...state,
        error: false,
        loading: false,
        confirmed: true
    },
    [actionTypes.error]: {
        ...state,
        error: true,
        loading: false
    },
    [actionTypes.write]: {
        ...state,
        value:payload
},
    [actionTypes.check]: {
        ...state,
        loading: true
    },
    [actionTypes.delete]: {
        ...state,
        deleted: true
    },
    [actionTypes.reset]: {
        ...state,
        confirmed: false,
        deleted: false,
        value: ''
    },
});
const reducer = (state,action) => {
    if (reducerObject(state)[action.type]) {
        return reducerObject(state,action.payload)[action.type]
    } else {
        returnstate;
    }
}

export {UseReducer};

Un gran poder, conlleva una gran responsabilidad.

ayuda! tenia que haber parado hace 5 clases, esto est谩 muy interesante.

Soy de los que tipean mal las palabras <3
````js le falto el onCheck en el objeto actionTypes, mi c贸digo declarativo con reducers: import { useEffect, useReducer } from "react"; const SECURITY_CODE = "paradigma"; function UseReducer({ name }) { const initialState = { value: "", error: false, loading: false, deleted: false, confirmed: false, }; const actionTypes = { error: "ERROR", confirm: "CONFIRM", check: "CHECK", write: "WRITE", delete: "DELETE", reset: "RESET", }; const reducer = (state, action) => { switch (action.type) { case actionTypes.error: return { ...state, error: true, loading: false, }; case actionTypes.confirm: return { ...state, loading: false, confirmed: true, }; case actionTypes.check: return { ...state, loading: true, error: false, }; case actionTypes.write: return { ...state, value: action.payload, }; case actionTypes.delete: return { ...state, deleted: true, }; case actionTypes.reset: return { ...state, deleted: false, confirmed: false, }; default: return state; } }; const [state, dispatch] = useReducer(reducer, initialState); useEffect(() => { console.log("iniciando efecto"); if (state.loading) { console.log("Haciendo validaci贸n en efecto"); setTimeout(() => { if (state.value !== SECURITY_CODE) { onError(); } else { onConfirm(); } }, 3000); } }, [state.loading]); const onError = () => { dispatch({ type: actionTypes.error }); }; const onConfirm = () => { dispatch({ type: actionTypes.confirm }); }; const onCheck = () => { dispatch({ type: actionTypes.check }); }; const onWrite = (event) => { dispatch({ type: actionTypes.write, payload: event.target.value }); }; const onDelete = () => { dispatch({ type: actionTypes.delete }); }; const onReset = () => { dispatch({ type: actionTypes.reset }); }; if (!state.deleted && !state.confirmed) { return (

{name}

Por favor, escribe el c贸digo de seguridad.

{state.error &&

Error codigo incorrecto

} {state.loading &&

cargando...

} <input type="text" placeholder="escribe el godigo de seguridad" onChange={onWrite} /> <button onClick={onCheck}>Comprobar</button>
); } else if (!state.deleted && state.confirmed) { return ( <>

Seguro que quiere eliminar?

<button onClick={onDelete}>si, eliminar</button> <button onClick={onReset}>no, quiero cancelar</button> ); } else { return ( <>

Eliminado con 茅xito

<button onClick={onReset}>resetear, volver atr谩s</button> ); } } export { UseReducer }; ```le falto el onCheck en el objeto actionTypes, mi c贸digo declarativo con reducers: import { useEffect, useReducer } from "react"; const SECURITY\_CODE = "paradigma"; function UseReducer({ name }) { const initialState = { value: "", error: false, loading: false, deleted: false, confirmed: false, }; const actionTypes = { error: "ERROR", confirm: "CONFIRM", check: "CHECK", write: "WRITE", delete: "DELETE", reset: "RESET", }; const reducer = (state, action) => { switch (action.type) { case actionTypes.error: return { ...state, error: true, loading: false, }; case actionTypes.confirm: return { ...state, loading: false, confirmed: true, }; case actionTypes.check: return { ...state, loading: true, error: false, }; case actionTypes.write: return { ...state, value: action.payload, }; case actionTypes.delete: return { ...state, deleted: true, }; case actionTypes.reset: return { ...state, deleted: false, confirmed: false, }; default: return state; } }; const \[state, dispatch] = useReducer(reducer, initialState); useEffect(() => { console.log("iniciando efecto"); if (state.loading) { console.log("Haciendo validaci贸n en efecto"); setTimeout(() => { if (state.value !== SECURITY\_CODE) { onError(); } else { onConfirm(); } }, 3000); } }, \[state.loading]); const onError = () => { dispatch({ type: actionTypes.error }); }; const onConfirm = () => { dispatch({ type: actionTypes.confirm }); }; const onCheck = () => { dispatch({ type: actionTypes.check }); }; const onWrite = (event) => { dispatch({ type: actionTypes.write, payload: event.target.value }); }; const onDelete = () => { dispatch({ type: actionTypes.delete }); }; const onReset = () => { dispatch({ type: actionTypes.reset }); }; if (!state.deleted && !state.confirmed) { return ( \
\

{name}\

\

Por favor, escribe el c贸digo de seguridad.\

{state.error && \

Error codigo incorrecto\

} {state.loading && \

cargando... \

} \<input type="text" placeholder="escribe el godigo de seguridad" onChange={onWrite} /> \<button onClick={onCheck}>Comprobar\</button> \
); } else if (!state.deleted && state.confirmed) { return ( <> \

Seguro que quiere eliminar?\

\<button onClick={onDelete}>si, eliminar\</button> \<button onClick={onReset}>no, quiero cancelar\</button> \ ); } else { return ( <> \

Eliminado con 茅xito\

\<button onClick={onReset}>resetear, volver atr谩s\</button> \ ); } } export { UseReducer }; ````
import { useEffect, useReducer } from "react"; 聽 聽 const SECURITY\_CODE = "paradigma"; 聽 聽 function UseReducer({ name }) {聽 聽 const initialState = {聽 聽 value: "",聽 聽 error: false,聽 聽 loading: false,聽 聽 deleted: false,聽 聽 confirmed: false,聽 聽 }; 聽 聽 const actionTypes = {聽 聽 error: "ERROR",聽 聽 confirm: "CONFIRM",聽 聽 check: "CHECK",聽 聽 write: "WRITE",聽 聽 delete: "DELETE",聽 聽 reset: "RESET",聽 聽 }; 聽 聽 const reducer = (state, action) => {聽 聽 聽 switch (action.type) {聽 聽 聽 聽 case actionTypes.error:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 error: true,聽 聽 聽 聽 聽 聽 loading: false,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.confirm:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 loading: false,聽 聽 聽 聽 聽 聽 confirmed: true,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.check:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 loading: true,聽 聽 聽 聽 聽 聽 error: false,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.write:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 value: action.payload,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.delete:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 deleted: true,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.reset:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 deleted: false,聽 聽 聽 聽 聽 聽 confirmed: false,聽 聽 聽 聽 聽 };聽 聽 聽 聽 default:聽 聽 聽 聽 聽 return state;聽 聽 聽 }聽 聽 }; 聽 聽 const \[state, dispatch] = useReducer(reducer, initialState); 聽 聽 useEffect(() => {聽 聽 聽 console.log("iniciando efecto"); 聽 聽 聽 if (state.loading) {聽 聽 聽 聽 console.log("Haciendo validaci贸n en efecto");聽 聽 聽 聽 setTimeout(() => {聽 聽 聽 聽 聽 if (state.value !== SECURITY\_CODE) {聽 聽 聽 聽 聽 聽 onError();聽 聽 聽 聽 聽 } else {聽 聽 聽 聽 聽 聽 onConfirm();聽 聽 聽 聽 聽 }聽 聽 聽 聽 }, 3000);聽 聽 聽 }聽 聽 }, \[state.loading]); 聽 聽 const onError = () => {聽 聽 聽 dispatch({ type: actionTypes.error });聽 聽 }; 聽 聽 const onConfirm = () => {聽 聽 聽 dispatch({ type: actionTypes.confirm });聽 聽 }; 聽 聽 const onCheck = () => {聽 聽 聽 dispatch({ type: actionTypes.check });聽 聽 }; 聽 聽 const onWrite = (event) => {聽 聽 聽 dispatch({ type: actionTypes.write, payload: event.target.value });聽 聽 }; 聽 聽 const onDelete = () => {聽 聽 聽 dispatch({ type: actionTypes.delete });聽 聽 }; 聽 聽 const onReset = () => {聽 聽 聽 dispatch({ type: actionTypes.reset });聽 聽 }; 聽 聽 if (!state.deleted && !state.confirmed) {聽 聽 聽 return (聽 聽 聽 聽 \
聽 聽 聽 聽 聽 \

{name}\

聽 聽 聽 聽 聽 \

Por favor, escribe el c贸digo de seguridad.\

聽 聽 聽 聽 聽 {state.error && \

Error codigo incorrecto\

}聽 聽 聽 聽 聽 {state.loading && \

cargando... \

}聽 聽 聽 聽 聽 \<input聽 聽 聽 聽 聽 聽 type="text"聽 聽 聽 聽 聽 聽 placeholder="escribe el godigo de seguridad"聽 聽 聽 聽 聽 聽 onChange={onWrite}聽 聽 聽 聽 聽 />聽 聽 聽 聽 聽 \<button onClick={onCheck}>Comprobar\</button>聽 聽 聽 聽 \
聽 聽 聽 );聽 聽 } else if (!state.deleted && state.confirmed) {聽 聽 聽 return (聽 聽 聽 聽 <>聽 聽 聽 聽 聽 \

Seguro que quiere eliminar?\

聽 聽 聽 聽 聽 \<button onClick={onDelete}>si, eliminar\</button>聽 聽 聽 聽 聽 \<button onClick={onReset}>no, quiero cancelar\</button>聽 聽 聽 聽 \聽 聽 聽 );聽 聽 } else {聽 聽 聽 return (聽 聽 聽 聽 <>聽 聽 聽 聽 聽 \

Eliminado con 茅xito\

聽 聽 聽 聽 聽 \<button onClick={onReset}>resetear, volver atr谩s\</button>聽 聽 聽 聽 \聽 聽 聽 );聽 聽 }聽 聽 } 聽 聽 export { UseReducer };
le falto el onCheck en el objeto actionTypes, mi c贸digo declarativo con reducers: 聽 聽 import { useEffect, useReducer } from "react"; 聽 聽 const SECURITY\_CODE = "paradigma"; 聽 聽 function UseReducer({ name }) {聽 聽 const initialState = {聽 聽 value: "",聽 聽 error: false,聽 聽 loading: false,聽 聽 deleted: false,聽 聽 confirmed: false,聽 聽 }; 聽 聽 const actionTypes = {聽 聽 error: "ERROR",聽 聽 confirm: "CONFIRM",聽 聽 check: "CHECK",聽 聽 write: "WRITE",聽 聽 delete: "DELETE",聽 聽 reset: "RESET",聽 聽 }; 聽 聽 const reducer = (state, action) => {聽 聽 聽 switch (action.type) {聽 聽 聽 聽 case actionTypes.error:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 error: true,聽 聽 聽 聽 聽 聽 loading: false,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.confirm:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 loading: false,聽 聽 聽 聽 聽 聽 confirmed: true,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.check:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 loading: true,聽 聽 聽 聽 聽 聽 error: false,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.write:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 value: action.payload,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.delete:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 deleted: true,聽 聽 聽 聽 聽 };聽 聽 聽 聽 case actionTypes.reset:聽 聽 聽 聽 聽 return {聽 聽 聽 聽 聽 聽 ...state,聽 聽 聽 聽 聽 聽 deleted: false,聽 聽 聽 聽 聽 聽 confirmed: false,聽 聽 聽 聽 聽 };聽 聽 聽 聽 default:聽 聽 聽 聽 聽 return state;聽 聽 聽 }聽 聽 }; 聽 聽 const \[state, dispatch] = useReducer(reducer, initialState); 聽 聽 useEffect(() => {聽 聽 聽 console.log("iniciando efecto"); 聽 聽 聽 if (state.loading) {聽 聽 聽 聽 console.log("Haciendo validaci贸n en efecto");聽 聽 聽 聽 setTimeout(() => {聽 聽 聽 聽 聽 if (state.value !== SECURITY\_CODE) {聽 聽 聽 聽 聽 聽 onError();聽 聽 聽 聽 聽 } else {聽 聽 聽 聽 聽 聽 onConfirm();聽 聽 聽 聽 聽 }聽 聽 聽 聽 }, 3000);聽 聽 聽 }聽 聽 }, \[state.loading]); 聽 聽 const onError = () => {聽 聽 聽 dispatch({ type: actionTypes.error });聽 聽 }; 聽 聽 const onConfirm = () => {聽 聽 聽 dispatch({ type: actionTypes.confirm });聽 聽 }; 聽 聽 const onCheck = () => {聽 聽 聽 dispatch({ type: actionTypes.check });聽 聽 }; 聽 聽 const onWrite = (event) => {聽 聽 聽 dispatch({ type: actionTypes.write, payload: event.target.value });聽 聽 }; 聽 聽 const onDelete = () => {聽 聽 聽 dispatch({ type: actionTypes.delete });聽 聽 }; 聽 聽 const onReset = () => {聽 聽 聽 dispatch({ type: actionTypes.reset });聽 聽 }; 聽 聽 if (!state.deleted && !state.confirmed) {聽 聽 聽 return (聽 聽 聽 聽 \
聽 聽 聽 聽 聽 \

{name}\

聽 聽 聽 聽 聽 \

Por favor, escribe el c贸digo de seguridad.\

聽 聽 聽 聽 聽 {state.error && \

Error codigo incorrecto\

}聽 聽 聽 聽 聽 {state.loading && \

cargando... \

}聽 聽 聽 聽 聽 \<input聽 聽 聽 聽 聽 聽 type="text"聽 聽 聽 聽 聽 聽 placeholder="escribe el godigo de seguridad"聽 聽 聽 聽 聽 聽 onChange={onWrite}聽 聽 聽 聽 聽 />聽 聽 聽 聽 聽 \<button onClick={onCheck}>Comprobar\</button>聽 聽 聽 聽 \
聽 聽 聽 );聽 聽 } else if (!state.deleted && state.confirmed) {聽 聽 聽 return (聽 聽 聽 聽 <>聽 聽 聽 聽 聽 \

Seguro que quiere eliminar?\

聽 聽 聽 聽 聽 \<button onClick={onDelete}>si, eliminar\</button>聽 聽 聽 聽 聽 \<button onClick={onReset}>no, quiero cancelar\</button>聽 聽 聽 聽 \聽 聽 聽 );聽 聽 } else {聽 聽 聽 return (聽 聽 聽 聽 <>聽 聽 聽 聽 聽 \

Eliminado con 茅xito\

聽 聽 聽 聽 聽 \<button onClick={onReset}>resetear, volver atr谩s\</button>聽 聽 聽 聽 \聽 聽 聽 );聽 聽 }聽 聽 } 聽 聽 export { UseReducer };
Para esto tambien se pueden utilizar los enums de typescript. Aqui un ejemplo de unos contadores implementando estos enums. ```js export type CountersState = { counterA: number; counterB: number; } export type Action = { type: ActionTypes; } export enum ActionTypes { INCREMENT_COUNTER_A = 'INCREMENT_COUNTER_A', DECREMENT_COUNTER_A = 'DECREMENT_COUNTER_A', INCREMENT_COUNTER_B = 'INCREMENT_COUNTER_B', DECREMENT_COUNTER_B = 'DECREMENT_COUNTER_B', RESET_COUNTER_A = 'RESET_COUNTER_A', RESET_COUNTER_B = 'RESET_COUNTER_B', } export type ReducerObject = { [ActionTypes.INCREMENT_COUNTER_A]: CountersState, [ActionTypes.DECREMENT_COUNTER_A]: CountersState, [ActionTypes.INCREMENT_COUNTER_B]: CountersState, [ActionTypes.DECREMENT_COUNTER_B]: CountersState, [ActionTypes.RESET_COUNTER_A]: CountersState, [ActionTypes.RESET_COUNTER_B]: CountersState, } const initialState: CountersState = { counterA: 0, counterB: 0, } const reducerObject = (state: CountersState): ReducerObject => ( { [ActionTypes.INCREMENT_COUNTER_A]: {...state, counterA: state.counterA + 1}, [ActionTypes.DECREMENT_COUNTER_A]: {...state, counterA: state.counterA - 1}, [ActionTypes.INCREMENT_COUNTER_B]: {...state, counterB: state.counterB + 1}, [ActionTypes.DECREMENT_COUNTER_B]: {...state, counterB: state.counterB - 1}, [ActionTypes.RESET_COUNTER_A]: {...state, counterA: 0}, [ActionTypes.RESET_COUNTER_B]: {...state, counterB: 0}, } ) const reducer = (state: CountersState, action: Action): CountersState => { if(reducerObject(state)[action.type]) return reducerObject(state)[action.type] else return state } function UseReducer() { const [state, dispatch] = useReducer(reducer, initialState); return ( <>

UseState

UseReducer

Counter A

{state.counterA}

<button onClick={() => dispatch({type: ActionTypes.DECREMENT_COUNTER_A})}>-</button> <button onClick={() => dispatch({type: ActionTypes.RESET_COUNTER_A})}>Reset</button> <button onClick={() => dispatch({type: ActionTypes.INCREMENT_COUNTER_A})}>+</button>

Counter B

{state.counterB}

<button onClick={() => dispatch({type: ActionTypes.DECREMENT_COUNTER_B})}>-</button> <button onClick={() => dispatch({type: ActionTypes.RESET_COUNTER_B})}>Reset</button> <button onClick={() => dispatch({type: ActionTypes.INCREMENT_COUNTER_B})}>+</button>

) } export default UseReducer ```

no me ganaste, porque yo te puse en pausa mientras lo hice. T茅cnicamente detuve tu tiempo. as铆 que a pesar de usar 鈥榗谩mara r谩pida鈥 yo claramente sal铆 ganador

C贸digo de la clase en TypeScript:
Debo decir que en este caso TS nos ofrece unas interesantes formas de trabajar esto:

import { ChangeEvent, FC, useEffect, useReducer } from "react"

type Props = {
    name: string
}

type State = {
    value: string,
    error: boolean,
    loading: boolean,
    deleted: boolean,
    confirmed: boolean,
}

enum ActionTypes {
    CHECK = 'CHECK',
    ERROR = 'ERROR',
    CONFIRM = 'CONFIRM',
    DELETE = 'DELETE',
    RESET = 'RESET',
    WRITE = 'WRITE',
}

interface Action {
    type: ActionTypes,
    payload?: any
}

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


const SECURITY_CODE = 'paradigma';


const UseReducer:FC<Props> = ({ name }) => {
    const [state, dispatch] = useReducer(reducer, initialState);

    const onConfirmed = () => {dispatch({ type: ActionTypes.CONFIRM })};
    const onError = ()=>{dispatch({ type: ActionTypes.ERROR })};
    const onWrite = ({ target : { value }}:ChangeEvent<HTMLInputElement>)=>{dispatch({ type: ActionTypes.WRITE , payload: value})};
    const onCheck = ()=>{dispatch({ type: ActionTypes.CHECK })};
    const onDelete = ()=>{dispatch({ type: ActionTypes.DELETE })};
    const onReset = ()=>{dispatch({ type: ActionTypes.RESET })};

    console.log(state);

    useEffect(()=>{
        console.log('Empezando el efecto');
        if(state.loading){
            console.log(state.  loading);
            setTimeout(()=>{
                console.log("Haciendo la validaci贸n");
                if(state.value === SECURITY_CODE){
                    onConfirmed();
                } else {
                    onError();
                }
                console.log("Terminando la validaci贸n");
            },3000)
        }
        console.log('Terminando el efecto');
    },[state.loading]);


    if(!state.deleted && !state.confirmed){
        return(
            <div>
                <h2>Eliminar { name }</h2>
                <p>Por favor, escribe el c贸digo de seguridad para comprobar que quieres eliminar</p>
    
                {state.error && !state.loading && (
                    <p>El c贸digo es incorrecto</p>
                )}
    
                {state.loading && (
                    <p>Cargando ...</p>
                )}
    
                <input 
                    type="text" 
                    placeholder="C贸digo de seguridad" 
                    value={state.value}
                    onChange={onWrite}
                />
    
                <button
                    onClick={()=>{
                        onCheck();
                    }}
                >Comprobar</button>
            </div>
    )} else if(!state.deleted && state.confirmed) {
        return(
            <>
                <p>驴Seguro que quieres eliminar { name }</p>
                <button
                    onClick={onDelete}
                >Si, eliminar</button>
                <button
                    onClick={onReset}
                >No, volver</button>
            </>
        )
    } else {
        return(
            <>
                <p>Estado de eliminaci贸n</p>
                <button
                    onClick={onReset}
                >Resetear, volver atr谩s</button>
            </>
        )
    }

}

const reducerObject = (state: State, action:Action): {[k in ActionTypes]: State} => ({
    CONFIRM:{
        ...state,
        loading: false,
        error: false,
        confirmed: true,
    },
    ERROR: {
        ...state,
        loading: false,
        error: true,
    },
    CHECK: {
        ...state,
        loading: true,
    },
    DELETE:{
        ...state,
        deleted: true
    },
    RESET: {
        ...state,
        confirmed: false,
        deleted: false,
        value: '',
    },
    WRITE:{
        ...state,
        value: action.payload
    }
});


const reducer = (state: State, action: Action) : State =>reducerObject(state, action)[action.type] || state;

export { UseReducer }