したがって、React Context + TypeScriptで非常に奇妙な問題が発生しています。
上記の例では、私が実際に実行しようとしていることがわかります。基本的に、私は新しいuseContextメソッドで状態を管理しており、完全に機能します。
しかし、これをボックスで実行しようとすると、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>
);
}
エラーメッセージ:
Type '{ state: { isAuth: boolean; user: string; }; dispatch:
Dispatch<Actions>; }' is missing the following properties from type
'IState': isAuth, user
私が使用しているコードは、私が自分のボックスで使用しているものとまったく同じです。サンドボックスからコードをダウンロードして実行してみましたが、機能しません。
VSCode 1.31を使用しています
私は自分のコンテキストの作成方法を次のように変更した場合、それをなんとか推論することができました。
export const AdminStore = React.createContext(initialState);
に
export const AdminStore = React.createContext(null);
Valueプロパティはそのエラーをスローしなくなりました。
ただし、現在はuseContextがエラーを返します。状態がnullに存在しません。また、コンテキストのdefaultStateを{}に設定した場合も同じです。
そしてもちろん
React.createContext();
次に、TSはdefaultValueが提供されていないことを叫びます。
サンドボックスでは、コンテキストオブジェクトの作成の3つのバージョンすべてが正常に機能します。
アドバイスを事前にありがとう。
私はこれで楽しい時間を過ごしたので、自分が思いついたものを共有したいと思いました。
SidebarProps
は、コンテキストの状態を表します。レデューサーアクション以外のすべては、基本的にそのまま使用できます。
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;