No tienes acceso a esta clase

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

Adquiere por un a帽o todos los cursos, escuelas y certificados por un precio especial.

Antes: $249

Currency
$219/a帽o

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Comprar ahora

Termina en:

0D
2H
27M
49S

Estados semideclarativos con useState

11/19
Recursos

Aportes 29

Preguntas 3

Ordenar por:

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

o inicia sesi贸n.

Ejemplo de estado imperativo:

<button
   onClick={() =>
       setState({
           ...state,
           loading: true
       })
   }>Comprobar</button>

Ejemplo de estado declarativo:

const onCheck = () => {
   setState({
       ...state,
       loading: true
   })
}
 
...
<button
   onClick={() =>
       onCheck()
   }>Comprobar</button>

jajajajaj yo tambien me qued茅 pensando como se decia comprobar en Ingles xdd
Lo habia llamado onValidate ya que no recordaba.

En los botones simplemente puede ponerlo de esta manera

onClick={onCheck}

asi escribe menos codigo y es un poco mas entendible,
si la funcion recibe un parametro se debe hacer asi

onChange={(e) => onWrite(e)}

Codigo cada vez m谩s declarativo:

  • Se usa funciones actualizadoras de estados con nombres muy informativos sobre el proceso.
  • Nos liberan de tener que indicar en cada parte del c贸digo principal cual es el nuevo proceso, estado o acci贸n.

En mi experiencia, cuando estamos en los primeros pasos de desarrollando de una soluci贸n, el c贸digo tiende a ser m谩s imperativo, buscando que la soluci贸n haga lo que necesitas, luego que ya tienes la soluci贸n, comienzas el proceso de refactorizaci贸n y lo vuelves m谩s declarativo. Es un proceso natural, adem谩s ayuda a reutilizar el c贸digo y tambi茅n hacerlo m谩s legible

state.value === SECURITY_CODE ? onConfirm() : onError();

He aprovechado y en vez de poner if-else lo he hecho en una linea.

El profe dice 鈥ac谩 arriba tenemos m谩s l铆neas de c贸digo, pero ac谩 abajo nuestro c贸digo se ve m谩s limpio鈥.

Creo que el libro Clean Code se menciona algo como 鈥(鈥) no pierdas tiempo escribiendo la documentaci贸n, escribe c贸digo que sea entendible a simple vista y luego documentas鈥.
Siento que el profe hace hincapi茅 en eso cuando escribe:

if ( condition ) {
	onConfirm();
} else {
	onError();
}

Antes de ir a la siguiente clase yo trate de hacer a este componente lo mas declarativo que pude y este fue el resultado final del return

return (
    <div>
      <h2>{renderTitle(confirmation, deleted, name)}</h2>

      {renderContent(
        name,
        confirmation,
        deleted,
        validation,
        loading,
        state,
        setState
      )}
    </div>
  );

Obviamente la funci贸n renderContent, as铆 como la de renderTitle son funciones que no agregue, pero estas funciones se encargan de toda la l贸gica por detr谩s para solo retornar el bloque de jsx que hay que regresar y la aplicaci贸n funciona bien

C贸digo de la clase

const onConfirm = ()=>{
        setState({ 
            ...state,
            error: false, 
            loading: false ,
            confirmed: true,
        });
    }

const onError = ()=>{
        setState({ 
            ...state,
            error: true, 
            loading: false 
        });
    }    	

const onWrite = (event)=>{
        setState({ 
            ...state,
            value: event.target.value,
        });
    }

const onCheck = ()=>{
        setState({ 
            ...state,
            loading: true 
        });
    }

 const onDelete = ()=>{
        setState({
            ...state,
            deleted: true,
        })
    }

 const onReset = ()=>{
        setState({
            ...state,
            confirmed: false,
            deleted: false,
            value:'',
        })
    }
if(!state.deleted && !state.confirmed){
        return (
            <div>
                <h2>Eliminar {name}</h2>
                <p>Por favor, escriba el c贸digo de seguridad.</p>
    
                {(state.error && !state.loading ) && (
                    <p>El c贸digo es 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.confirmed && !state.deleted){
        return(
            <React.Fragment>
                <p>驴Seguro que quieres eliminar UseState?</p>
                <button
                    onClick={()=>{
                        onDelete();
                    }}
                >Si, eliminar</button>
                <button
                    onClick={()=>{
                        onReset();
                    }}
                >No, volver</button>
            </React.Fragment>
        )
    } else {
        return (
            <React.Fragment>
                <p>Eliminado con exito</p>
                <button
                    onClick={()=>{
                        onReset();
                    }}
                >Recuperar UseState</button>
            </React.Fragment>
        )
    }

Me encanta la forma semi-declarativa de usar estados!

por aqui dejo el link de platzi English Academy 馃ぃ :https://platzi.com/idioma-ingles/ 馃ぃ

B谩sicamente, lo usamos para 鈥渙ptimizar鈥 nuestro c贸digo y evitar el DRY (Don鈥檛 repeat your self)

La verdad es que quiza sea la costumbre o nolose, pero me acomodo mas con la primera forma, la Imperativa.

Por otro lado, me gustar铆a preguntar, 驴Cuando usar cualquiera de los dos enfoques.?

Intentando responderme solo y pensando en que dijo Juan que son igual de efectivos, supongno que es dependiendo de tu App como dijo y tambien de el equipo de trabajo con quien estes codeando. Y para concluir, aprender las dos formas.

Prefiero esta forma de programar, sinceramente

UseState: modo imperativo, en Nextj js, TypeScript, tailwind CSS y variables de entorno en .env.local

import React from "react";

const UseState = (props: { name: string }) => {
  const [state, setState] = React.useState({
    value: "",
    error: false,
    loading: false,
    deleted: false,
    confirmed: false,
  });
  const { name } = props;
  React.useEffect(() => {
    console.log("empezando el efecto");
    if (!!state.loading) {
      setTimeout(() => {
        console.log("haciendo la validaci贸n");
        if (state.value !== process.env.NEXT_PUBLIC_SECURITY_CODE) {
          setState({ ...state, error: true, loading: false });
        } else {
          setState({ ...state, error: false, loading: false, confirmed: true });
        }
        console.log("finalizando la validaci贸n");
      }, 1500);
    }
    console.log("finalizando el efecto");
  }, [state]);
  if (!state.deleted && !state.confirmed) {
    return (
      <section className="flex flex-col items-center w-screen h-96 justify-evenly">
        <h3 className="text-3xl font-bold">Eliminar {name}</h3>
        <p className="text-2xl ">Por favor, escribe el c贸digo de seguridad</p>
        {state.error && !state.loading && (
          <p className="text-xl font-medium text-red-600">
            error: el c贸digo es incorrecto
          </p>
        )}
        {state.loading && (
          <p className="text-xl font-medium text-green-600">...cargando</p>
        )}
        <div className="flex ">
          <input
            placeholder="C贸digo de seguridad"
            className="p-2 mx-4 text-xl text-center border-2 rounded-md"
            value={state.value}
            onChange={(e) => {
              e.preventDefault();
              setState({ ...state, value: e.target.value });
            }}
          />
          <button
            className="p-2 text-xl font-semibold bg-green-200 border-2 border-green-700 rounded-md shadow-lg cursor-pointer text-slate-950 hover:bg-green-800 hover:text-slate-100"
            onClick={() => setState({ ...state, loading: true })}
          >
            Comprobar
          </button>
        </div>
      </section>
    );
  } else if (!!state.confirmed && !state.deleted) {
    return (
      <section className="flex flex-col items-center w-screen h-96 justify-evenly">
        <h2 className="mt-4 text-3xl font-bold text-center text-stone-800">
          驴Seguro que quiere eliminar UseState?
        </h2>
        <div className="flex items-center mt-4 justify-evenly">
          <button
            className="px-4 py-2 mx-16 text-xl font-medium bg-red-600 border-2 rounded-lg shadow-lg text-stone-100"
            onClick={() => {
              setState({
                ...state,
                deleted: true,
              });
            }}
          >
            Si, eliminar
          </button>
          <button
            className="px-4 py-2 mx-16 text-xl font-medium bg-green-600 border-2 rounded-lg shadow-lg text-stone-100"
            onClick={() => {
              setState({
                ...state,
                confirmed: false,
                value: "",
              });
            }}
          >
            No, volver atr谩s
          </button>
        </div>
      </section>
    );
  } else {
    return (
      <section className="flex flex-col items-center w-screen h-96 justify-evenly">
        <h2 className="mt-4 text-3xl font-bold text-center text-stone-800">
          Eliminado con 茅xito
        </h2>
        <button
          className="px-4 py-2 mx-16 text-xl font-medium bg-green-600 border-2 rounded-lg shadow-lg text-stone-100"
          onClick={() => {
            setState({
              ...state,
              confirmed: false,
              deleted: false,
              value: "",
            });
          }}
        >
          Recuperar UseState
        </button>
      </section>
    );
  }
};

export default UseState;

No se que opinan si en vez de colocar varias funciones como onConfirm() y onError(), colocar una funcion por ejemplo onChangeState() y que esta sea la unica que maneje el cambio de estos estados. Por ejemplo algo asi:

    const onChangeState = (
    newValue = state.value,
    newError = state.error,
    newLoading = state.loading,
    newDeleted = state.deleted,
    newConfirmed = state.confirmed
  ) => {
    setState({
      value: newValue,
      loading: newLoading,
      error: newError,
      deleted: newDeleted,
      confirmed: newConfirmed,
    });
  };

De esta manera, cada vez que necesites actualizar un estado, realizas el llamado de esta funcion y envias unicamente los estados a actualizar, los que no envies simplemente mantendran su valor original por defecto.

En lugar del metodo onCheck yo lo llam茅 y me parece mejor onVerified

clean code 鉂わ笍

Para no confundirse mucho cuando se est谩 haciendo la parte de la funci贸n onWrite

// La funci贸n recibe un evento de forma predeterminada al ser llamada, este se escribe como par谩metro para poder utilizarla m谩s adelante, y en el value le damos su valor que se encuentra en el target de ese evento.
const onWrite = (e) => {
  setState({
    ...state,
    value: e.target.value
  })
}
// Al escribir solo el nombre de la funci贸n, sin ejecutarla con los par茅ntesis estamos haciendo una referencia a esa funci贸n, en otras palabras ser铆a como si la escribi茅ramos directamente, tiene el mismo comportamiento.
<input onChange={onWrite} />

Como tengo la extensi贸n de ErrorLens, esta me indicaba que habr铆a problemas de render por las dependencias de useEffect. Para evitar esto, necesitamos usar a useCallback.
En este art铆culo de Medium dan un ejemplo de c贸mo usarlos juntos

Y les dejo el c贸digo usando a ambos que funciona correctamente:

import { useState, useEffect, useCallback } from 'react'

import './UseState.css'

const SECURITY_CODE = 'techzone'

function UseState({name}) {
  const [state, setState] = useState({
    value: '',
    error: false,
    loading: false,
    deleted: false,
    confirmed: false,
  })

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

  const onCheck = () => {
    setState({
      ...state,
      loading: true
    })
  }

  const onDelete = () => {
    setState({
      ...state,
      deleted: true
    })
  }

  const onReset = () => {
    setState({
      ...state,
      confirmed: false,
      deleted: false,
      value: ''
    })
  }

  const changeState = useCallback(() => {
    const onConfirm = () => {
    setState({
      ...state,
      error: false,
      confirmed: true,
      loading: false
    })
  }

  const onError = () => {
    setState({
      ...state,
      error: true,
      loading: false
    })
  }

    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={(e) => onWrite(e.target.value)}
        />
        <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>
      </>
    )
  }
}

export { UseState }

Yo lo hice as铆

Validation lo ejecuta el button Confirmar

const validation = () => {
    setState({
      ...state,
      loading: true,
      error: false,
    });

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

  const toggleConfirm = (delValue, conValue) => {
    setState({
      ...state,
      deleted: delValue,
      confirm: conValue,
    });
  };
    
  const reStart = () => {
    setState({
      ...state,
      deleted: false,
      confirm: false,
      value: "",
    });
  };

Use effect

  setTimeout(() => {
      setState({
        ...state,
        error: state.value !== SECURITY_CODE,
        confirm: state.value === SECURITY_CODE,
        loading: false,
      });
    }, 1500);
  };

Algo de documentaci贸n sobre estos paradigmas: https://www.educative.io/blog/declarative-vs-imperative-programming

Hola a todos, espero esten teniendo un icreible dia de codigo devs!!. Les dejo mi soluci贸n para onCheck ya que considero que en el useEffect no es necesario hacer un if else.
.
Si opinas diferente porfavor dejame saberlo en los comentarios para aprender juntos desde diferentes puntos de vista!
.

.

C贸digo de la clase en TypeScript

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

type Props = {
    name: string
}

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

const SECURITY_CODE = 'paradigma';


const UseState:FC<Props> = ({ name }) => {
    const [state, setState] = useState<State>({
        value: '',
        error: false,
        loading: false,
        confirmed: false,
        deleted: false,
    });

    const onConfirmed = () => {
        setState({
            ...state,
            loading: false,
            error: false,
            confirmed: true,
        })
    };

    const onError = ()=>{
        setState({
            ...state,
            loading: false,
            error: true,
        })
    };

    const onWrite = ({ target : { value }}:ChangeEvent<HTMLInputElement>)=>{
        setState({
            ...state,
            value
        })
    };

    const onCheck = ()=>{
        setState({
            ...state,
            loading: true
        })
    }

    const onDelete = ()=>{
        setState({
            ...state,
            deleted: true
        })
    };

    const onReset = ()=>{
        setState({
            ...state,
            confirmed: false,
            deleted: false,
            value: '',
        })
    };

    console.log(state.value);

    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>
            </>
        )
    }

}

export { UseState }

Desde mi punto de vista, realice algunos cambios en los actualizadores del estado value que se recibe del input y tambi茅n como llamamos a cada uno de los estados mediante la desestructuraci贸n de objetos para evitar escribir siempre state.propiedad. A su vez en el useEffect utilice un operador ternario en la validaci贸n de la frase y asi mejorar la legibilidad del c贸digo quedando con la siguiente l贸gica:

const SECURITY_CODE = 'paradigma'

const UseState = ({ name }) =>{
    const [state, setState] = React.useState({loading: false, error: false, value: '', deleted: false, confirmed: false})
    const { loading, error, value, confirmed, deleted } = state

    const onConfirm = () =>{
        return setState({...state, loading: false, error: false, confirmed: true, value: ''})
    }

    const onError = () =>{
        return setState({...state, loading: false, error: true})
    }

    const onChangeValue = (value) =>{
        return setState({...state, value})
    }

    const onSubmit = () =>{
        return setState({...state, loading: !loading})
    }

    const onDelete = () =>{
        return setState({...state, deleted: true})
    }

    const onCancel = () =>{
        setState({...state, confirmed: false, deleted: false})
    }

    React.useEffect(()=>{
        if(loading){
            setTimeout(()=>{
                (value !== SECURITY_CODE)
                    ? onError()
                    : onConfirm()
            },3000)
        }
    }, [loading])

    if(!confirmed && !deleted){
        return (
            <div>
                <h2>Eliminar {name}</h2>
                <p>Por favor escribe el codigo de seguridad</p>
    
                {(!loading && !!error) && (<span>El codigo es incorrecto</span>)}
    
                {!!loading && (<span>Cargando</span>)}
    
                <input 
                value={value}
                placeholder="Codigo de seguridad"
                onChange={(event)=>onChangeValue(event.target.value)}/>

                <button onClick={onSubmit}>Comprobar</button>
            </div>
        )
    }else if(confirmed && !deleted){
        return (
            <>
                <p>Confirmacion de eliminacion, estas seguro?</p>
                <button onClick={onDelete}>Si, eliminar</button>

                <button onClick={onCancel}>No, cancelar</button>
            </>
        )
    }else{
        return (
            <>
                <p>Eliminado con exito</p>
                <button onClick={onCancel}>Recuperar SetState</button>
            </>
        )
    }
}

Mejorando mi propuesta anterior, se podr铆a tener un m茅todo que se encargue de todos:

function handleUpdateState(nuevoEstado){
	return setMiEstadoCompuesto({
		...miEstadoCompuesto,
		...nuevoEstado
	})
}

As铆 podr茅 actualizar uno o varios estado usando el mismo handle (handleUpdateState), por ejemplo:

handleUpdateState({ error: false })

handleUpdateState({ error: false, loading: true, confirmed: true })

C贸digo cada vez m谩s declarativo:

  • Se usa funciones actualizadoras de estados con nombres muy informativos sobre el proceso.
  • Nos liberan de tener que indicar en cada parte del c贸digo principal cual es el nuevo proceso, estado o acci贸n.

Para este ejemplo vamos a abstraer estos estados y crear un c贸digo m谩s declarativo que nos indique a que pantalla vamos a cambiar.

dentro de el componente vamos a escribir lo siguiente:

function UseState({ name }) {
  const onConfirm = () => {
    setState({
      ...state,
      loading: false,
      confirmed: true,
    });
  }

  ...
}

Como vemos estamos abstrayendo los estados de React en una funci贸n que explica que de manera declarativa que es lo que estamos haciendo.

Ahora cada vez que deseemos llamar a este evento vamos a llamar a esta funci贸n.

React.useEffect(() => {
    if(state.loading) {
      setTimeout(() => {
        if(state.value === SECURITY_CODE) {
          onConfirm();
        } ...
      },3000);
    }
  }, [state.loading]);

Ya teniendo este conocimiento podemos empezar a hacer el resto con los dem谩s, yo lo hice as铆:

function UseState({ name }) {
	const onChangeInput = (event) => {
    setState({
      ...state,
      value: event.target.value,
    });
  }

	const onSetUpValidate = () => {
    setState({
      ...state,
        error: false,
        loading: true,
      });
  }

  const onConfirm = () => {
    setState({
      ...state,
      loading: false,
      confirmed: true,
    });
  }

  const onError = () => {
    setState({
      ...state,
      loading: false,
      error: true,
    });
  }

  const onDelete = () => {
    setState({
      ...state,
      deleted: true,
    });
  }

  const onRepent = () => {
    setState({
      ...state,
      confirmed: false,
      deleted: false,
      value: '',
    })
  }
	 
	...
}

Esta es la manera en la que podemos tener un c贸digo un poco m谩s declarativo.