React Context API
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. con React Context API è possibile spostare lo stato al di fuori dell'applicazione ed accedervi direttamente da ogni singolo componenteQuesto approccio risulta molto utile nel caso di componenti molto annidati.
A questo punto posso creare un componente ShowUser che consuma i dati del contesto
Vedi anche React Context.
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. con React Context API è possibile spostare lo stato al di fuori dell'applicazione ed accedervi direttamente da ogni singolo componenteQuesto 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.createContextReact JSX: UserContext
import * 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 providerReact JSX: UserProvider
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 UserProviderReact JSX: Root UserProvider
import * 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
React JSX: ShowUser
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 modificarloReact JSX: ButtonUser
import * 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.