React Context fornisce un metodo alternativo per gestire lo stato dell'applicazione.
Normalmente lo stato di una applicazione viene mantenuto nel componente di
root e fatto passare, tramite le proprietà, agli altri componenti con la tecnica detta
Prop Drilling.
React Prop Drillingcon
React Context API è possibile spostare lo stato al di fuori dell'applicazione ed accedervi direttamente da ogni singolo componente
React ContextQuesto approccio risulta molto utile nel caso di componenti molto annidati.
Context
Per usare
React Context sono necessari 3 passi
- Definire un contesto
- Definire un provider
- Consumare il contesto
Definire un contesto
Il contesto va definito con l'istruzione
React.createContextimport * as React from 'react';
// come esempio gestisco lo stato dell'utente
export interface IUser {
loginName: string;
modified: Date;
}
// il contesto comprenderà la proprietà ed il metodo per modificare IUser
interface IUserContext {
user: IUser;
setUser: (loginName: IUser) => void
}
// creo il contesto
const UserContext = React.createContext<IUserContext | null>(null);
export default UserContext;
Definire un provider
Successivamente va completato con la definizione di un
provider import * as React from 'react';
import { FC, ReactElement, useState } from 'react';
export interface IUser {
loginName: string;
modified: Date;
}
interface IUserContext {
user: IUser;
setUser: (loginName: IUser) => void
}
// definisco il tipo di proprietà che verranno passate al Provider
type UserProviderProps = {
user: IUser, // valore di default del contesto
children: JSX.Element // gli elementi figli del provider
};
const UserContext = React.createContext<IUserContext | null>(null);
// creo una funzione (FC) che rappresenta il Provider
export const UserProvider: FC<UserProviderProps> = (props): ReactElement => {
// uso useState per memorizzare lo stato del contesto
const [user, setUser] = useState<IUser>({
loginName: props.user.loginName,
modified: new Date
});
return (
// definisco il Provider del context passando lo stato da memorizzare
<UserContext.Provider value={{ user, setUser }}>{props.children}</UserContext.Provider>
)
}
export default UserContext;
Consumare il contesto
Per poter
consumare il contesto, prima di tutto, devo fare il
wrap del componente di
root con il provider
UserProviderimport * as React from 'react';
import styles from './HelloWordContext.module.scss';
import { IHelloWordContextProps } from './IHelloWordContextProps';
import { UserProvider } from '../contexts/UserContext';
export default class HelloWordContext extends React.Component<IHelloWordContextProps, {}> {
public render(): React.ReactElement<IHelloWordContextProps> {
return (
<UserProvider user={{loginName: 'utente1', modified: new Date()}}>
<sectio className={`${styles.helloWordContext} ${hasTeamsContext ? styles.teams : ''}`}>
<ShowUser />
<hr />
<ButtonUser />
</section>
</UserProvider>
);
}
}
L'esempio è basato su un progetto
SPFx.
A questo punto posso creare un componente
ShowUser che
consuma i dati del contesto
import * as React from 'react';
import { FC, ReactElement } from 'react';
import UserContext from '../contexts/UserContext';
const ShowUser: FC = (): ReactElement => {
// recupero il contesto
const { user } = React.useContext(UserContext);
const modified = new Intl.DateTimeFormat('it-IT', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}).format(user?.modified)
return (
<span>LoginName: {user?.loginName}, modified: {modified}</span>
)
};
export default ShowUser;
Notare l'uso di Intl.DateTimeFormat(...) per formattare le date in italiano senza l'uso di librerie esterne.
Oltre a
visualizzare i dati del contesto, posso anche
modificarloimport * as React from 'react';
import { FC, ReactElement } from 'react';
import UserContext from '../contexts/UserContext';
const ButtonUser: FC = (): ReactElement => {
// recupero il contesto e quello che mi serve
const { user, setUser } = React.useContext(UserContext);
// creo un handler che al click modifica la data modified
const handlerClick = (): void => setUser({ loginName: user.loginName, modified: new Date() });
return (
<button type='button' onClick={handlerClick}>Set date</button>
)
};
export default ButtonUser;
Vedi anche
React Context.