web-dev-qa-db-ja.com

React TypescriptのcreateContextの問題?

したがって、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つのバージョンすべてが正常に機能します。

アドバイスを事前にありがとう。

14
bauervision

私はこれで楽しい時間を過ごしたので、自分が思いついたものを共有したいと思いました。

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;
1
Jerad