Reputation: 185
I have the following code;
import React, { useContext, useReducer, useEffect, } from 'react';
const AppContext = React.createContext({});
const App = () => {
let initialState = { lang: 'en', color: 'blue'};
let reducer = (state, action) => {
if (action === null ) {
localStorage.removeItem("action");
return initialState;
}
switch (action.type) {
case "change-language":
return { ...state, lang: action.payload };
default: return {initialState}
}
};
const localState = JSON.parse(localStorage.getItem("state")!);
let [state, dispatch] = useReducer(reducer, localState || initialState );
let value = { state, dispatch };
return (
<AppContext.Provider value={value}>
<LanguagePicker />
<Menu />
</AppContext.Provider>
);
}
const Menu = () => <MenuItem />;
const LanguagePicker = () => {
const {state, dispatch} = useContext(AppContext);
let setLanguage = lang => () => dispatch({ type: "change-language", payload: lang });
useEffect(() => {
localStorage.setItem("state", JSON.stringify(state));
}, [state]);
return (
<div>
<button onClick={setLanguage('en')}>English</button>
<button onClick={setLanguage('fr')}>French</button>
</div>
);
}
const MenuItem = () => {
const { state, dispatch } = useContext(AppContext);
return (
<div>
<p>Locale: {state.lang}</p>
</div>
);
}
export default App;
Now, this code runs perfectly fine in JS/JSX, but in typescript it gives the following error.
Property 'state' does not exist on type '{}'.ts(2339)
Property 'dispatch' does not exist on type '{}'.ts(2339)
@
const LanguagePicker = () => {
const {state, dispatch} = useContext(AppContext);
Question obviously becomes; how do i make the property exist on type {}? (Or, fool the compiler into thinking it exists. Why does it give this warning/compiler error in the first place?
I don't get it.
I've tried to define the state in an Interface, then App: React.Component<'any, Interface'>, (as i saw a post where that worked for class components, but to no avail.)
Someone pointing me in the right direction would be highly appreciated.
Upvotes: 2
Views: 1317
Reputation: 5657
useContext
can infer its types from the context object that is passed in as an argument, which is AppContext
.
const AppContext = React.createContext({});
The inferred type is {}
, and that's why you are getting that error.
You can fix this by passing in a type generic to createContext
:
interface ContextType {
state?: any;
dispatch?: any;
}
const AppContext = React.createContext<ContextType>({});
As @skovy said, you should have a better idea of state
and dispatch
types.
Upvotes: 2
Reputation: 5650
The problem is that the type being using for context is {}
because that's the value it's being initialized with. If you update the initial call to createContext
and pass in the correct type generic this should resolve your issue.
const AppContext = React.createContext<{
state?: any;
dispatch?: React.Dispatch<any>;
}>({});
These are pretty loose typings because state
can be any
value and anything can be dispatched so you may also want to define stronger types for what the actual context value is (but that's up to you and your use case).
Upvotes: 4