Primero hay que entender para que usaremos context en nuestras aplicaciones.
- Administración de estado
- Componentes de acceso global.
Para la administración de estados dispones de combinaciones con useState
y useReducer
.
De esta forma lo usaremos para administrar nuestro estado de forma global. Primero definiendo nuestro context, lo llamaremos AuthenticationContext, pero para resumir será AuthContext.
import React, { useCallback, useMemo } from 'react';
interface IUserInfo {
uuid: string;
username: string;
email: string;
name: string;
}
export interface IAuthContext {
userInfo?: IUserInfo;
setUserInfo: (user: IUserInfo) => void;
onLogin: (username: string) => Promise<IUserInfo | undefined>;
onLogout: () => Promise<void>;
}
export const AuthContext = React.createContext<IAuthContext>({
userInfo: undefined,
setUserInfo: (user) => {
throw new Error('Not yet implemented');
},
onLogin: (username) => {
throw new Error('Not yet implemented');
},
onLogout: () => {
throw new Error('Not yet implemented');
},
});
Nuestro AuthContext está compuesto por userInfo este atributo contendrá la información del usuario, setUserInfo nos permite asignar la información del usuario, onLogin nos permite ejecutar la petición para realizar el inicio de sesión en nuestra app.
Ahora es necesario definir nuestro Provider, este nos permitirá agregar la lógica necesaria para darle funcionalidad a nuestra aplicación. El nombre correcto para nuestro proveedor será AuthProvider y este hará uso del AuthContext.
interface Props {
children: JSX.Element;
}
export const AuthProvider = ({ children }: Props): JSX.Element => {
const { userInfo, setUserInfo } = useState<IUserInfo | undefined>(undefined);
// Iniciar Sesión
const onLogin = useCallback(
async (username) => {
const user = await fetch(<server_user_login>);
setUserInfo(user);
return user;
}, [setUserInfo]);
// Cerrar sesión
const onLogout = useCallback((userInfoLogout) => {
await fetch(<server_user_logout>);
setUserInfo(undefined);
}, [setUserInfo]);
const values = React.useMemo<IAuthContext>(() =>({
userInfo,
setUserInfo,
onLogin,
onLogout
}))
return (
<AuthContext.Provider value={...values}>
{children}
</AuthContext.Provider>
);
};
export default AuthProvider;
Haciendo uso de un useState
manejaremos nuestro estado userInfo, para nuestras funciones onLogin
y onLogout
son las encargadas de conectar nuestra app con el servidor usando peticiones HTTP usando fetch
o axios
.
Ya solo nos falta exponer los datos para poder hacer uso de ellos. Hacerlo de la siguiente manera nos permite centralizar el contexto y nos ahorramos una serie de validaciones, por ello usamos un hook
.
import { useContext } from 'react';
import { AuthContext, IAuthContext } from 'context/authContext';
export function useAuth(): IAuthContext {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth may be used inside of AuthContext');
}
return context;
}
¿Y como usamos todo esto ahora?
En nuestra app debemos integrar el Provider.
import { AuthProvider } from 'context/authContext';
const App = () => {
return (
<AuthProvider>
...
</AuthProvider>
);
};
export default App;
Y para usar los datos en nuestros componentes tenemos la siguiente via
import { useAuth } from 'hooks/useAuth';
import { useClosable } from 'hooks/useClosable';
import { SimpleConfirmDialog } from 'components/SimpleConfirmDialog';
export const LogoutButton = () => {
const { onLogout } = useAuth();
const [open, onOpen, onClose] = useClosable();
return (
<>
<Tooltip title="Cerrar Sesión">
<IconButton
onClick={onOpen}
type="submit"
color="secondary"
edge="end"
>
<ExitToAppIcon />
</IconButton>
</Tooltip>
<SimpleConfirmDialog
open={open}
onClose={onClose}
onConfirm={onLogout}
title="Cerrar sesión"
/>
</>)
}
Haciendo uso del hook
useAuth traemos toda la lógica que hemos centralizado en los procesos anteriores y esto hace más sencillo la creación de componentes dependientes de nuestro proveedor.
Espero que esta primera parte de esta entrada sea de gran ayuda a la hora de crear Contextos y proveedores en sus aplicaciones escritas en react.
Top comments (0)