J'ai donc un problème très étrange avec React Context + TypeScript.
Dans l'exemple ci-dessus, vous pouvez voir ce que j'essaie de faire fonctionne réellement. Essentiellement, je gère l'état avec la nouvelle méthode useContext, et cela fonctionne parfaitement.
Cependant, lorsque j'essaie de le faire sur ma boîte, il ne semble pas trouver les valeurs d'état transmises via useReducer.
export function AdminStoreProvider(props: any) {
const [state, dispatch] = useReducer(reducer, initialState);
// state.isAuth is avail here
// state.user is avail here
const value = { state, dispatch };
// value.state.isAuth is avail here
return (
/* value does not contain state once applied to the value prop */
<AdminStore.Provider value={value}>{props.children}
</AdminStore.Provider>
);
}
Message d'erreur:
Type '{ state: { isAuth: boolean; user: string; }; dispatch:
Dispatch<Actions>; }' is missing the following properties from type
'IState': isAuth, user
Gardez à l'esprit que le code que j'utilise est exactement ce que j'utilise sur ma boîte, j'ai même téléchargé le code à partir du bac à sable et essayé de l'exécuter, et cela ne fonctionne pas.
J'utilise VSCode 1.31
J'ai réussi à déduire que si je change la façon dont je crée mon contexte à partir de:
export const AdminStore = React.createContext(initialState);
à
export const AdminStore = React.createContext(null);
La propriété value ne renvoie plus cette erreur.
Cependant, useContext renvoie maintenant une erreur: l'état n'existe pas sur null. Et même si je mets defaultState pour le contexte à {}.
Et bien sûr, si je
React.createContext();
TS crie alors qu'aucune valeur par défaut n'est fournie.
Dans le bac à sable, les 3 versions de création de l'objet contextuel fonctionnent correctement.
Merci d'avance pour tout conseil.
J'ai passé un bon moment avec ça, alors j'ai pensé que je partagerais ce que j'avais imaginé.
SidebarProps
représente l'état du contexte. Tout le reste, à part les actions de réduction, peut essentiellement être utilisé tel quel.
import React, { createContext, Dispatch, Reducer, useContext, useReducer } from 'react';
interface Actions {
type: string;
value: any;
}
interface SidebarProps {
show: boolean;
content: JSX.Element | null;
}
interface SidebarProviderProps {
reducer: Reducer<SidebarProps, Actions>;
initState: SidebarProps;
}
interface InitContextProps {
state: SidebarProps;
dispatch: Dispatch<Actions>;
}
export const SidebarContext = createContext({} as InitContextProps);
export const SidebarProvider: React.FC<SidebarProviderProps> = ({ reducer, initState, children }) => {
const [state, dispatch] = useReducer(reducer, initState);
const value = { state, dispatch };
return (
<SidebarContext.Provider value={value}>
{children}
</SidebarContext.Provider>
);
};
export const useSidebar = () => useContext(SidebarContext);
const SidebarController: React.FC = ({ children }) => {
const initState: SidebarProps = {
show: false,
content: null
};
const reducer: Reducer<SidebarProps, Actions> = (state, action) => {
switch (action.type) {
case 'setShow':
return {
...state,
show: action.value
};
case 'setContent':
return {
...state,
content: action.value
};
default:
return state;
}
};
return (
<SidebarProvider reducer={reducer} initState={initState}>
{children}
</SidebarProvider>
);
};
export default SidebarController;