Как я могу правильно определить интерфейс типа при использовании React useContext?

У меня есть:

export interface AppStateType {
    isOnline: boolean
}

const AppContext = createContext([{}, () => { }]);

const AppProvider = (props) => {
    const [appState, setAppState] = useState<AppStateType>({
        isOnline: true
    })

    return <AppContext.Provider value={[appState, setAppState]}>
        {props.children}
    </AppContext.Provider>
}
export { AppContext, AppProvider }

Когда я пытаюсь его использовать:

const [appState, setAppState] = useContext<AppStateType>(AppContext)

Я получаю ошибку машинописного текста:

Argument of type 'Context<{}[]>' is not assignable to parameter of type 'Context<AppStateType>'.
  The types of 'Provider.propTypes.value' are incompatible between these types.
    Type 'Validator<{}[]>' is not assignable to type 'Validator<AppStateType>'.
      Type '{}[]' is not assignable to type 'AppStateType'.

person Shamoon    schedule 13.05.2020    source источник
comment
Этот ответ, вероятно, поможет вам - это то же созвездие .   -  person ford04    schedule 13.05.2020


Ответы (2)


Причина, по которой вы получаете эту ошибку, заключается в том, что тип возвращаемого значения Context не является AppStateType, а является массивом с двумя значениями. Первый - это AppState, а второй - диспетчер.

С помощью машинописного текста вы можете ввести контекст, когда он создан, например

const AppContext = createContext<[AppStateType, React.Dispatch<any>]>(null);

Опубликуйте это, вы можете просто использовать это как

const [appState, setAppState] = useContext(AppContext);

Образец демонстрации

ПРИМЕЧАНИЕ. Определите значение по умолчанию для createContext как null, поскольку оно будет использоваться только тогда, когда в дереве иерархии нет поставщика. В этом случае чаще всего это может быть ошибка.

person Shubham Khatri    schedule 13.05.2020
comment
Какую ошибку он выдает, потому что он хорошо компилируется для меня, если я создаю контекст вроде const AppContext = createContext<[AppStateType, React.Dispatch<any>]>(null);. Убедитесь, что вы передаете null в createContext в качестве аргументов, потому что это будет использоваться только в том случае, если в иерархии нет PRovider, что означает, что ваш код неверен, поэтому лучше выдать ошибку, чем остаться незамеченным - person Shubham Khatri; 13.05.2020
comment
да, передача null вместо [] - это вариант. Но это зависит от среды - это возможно только с отключенным параметром strict mode / strictNullChecks, как в песочнице (вы можете попробовать добавить "strictNullChecks": true в tsconfig.json). - person ford04; 13.05.2020
comment
Хм, он все еще работает, даже если я добавлю strictNullChecks в конфиг TS - person Shubham Khatri; 13.05.2020
comment
Вот копия вашей песочницы, где эти проверки активированы. - person ford04; 13.05.2020

Параметр для createContext - это значение контекста по умолчанию, см. здесь Итак, если ваш тип контекста это состояние и установленное состояние так

[AppStateType,React.Dispatch<React.SetStateAction<AppStateType>>]

Вам нужно указать значение по умолчанию

const AppContext = createContext([{}, () => { }]);

Должно быть

const AppContext = createContext<[AppStateType,React.Dispatch<React.SetStateAction<AppStateType>>]>([{isOnline:false},()=> false]);
person Moshe Sommers    schedule 13.05.2020
comment
Тогда я не могу установить appState - person Shamoon; 13.05.2020
comment
@Shamoon Вы правы, я обновил свой ответ, чтобы иметь массив State и sSetState в качестве типа для контекста, позволяющего передавать массив в качестве значения - person Moshe Sommers; 13.05.2020