So, im trying to import my existing React app with JSX to TSX, but for some reason the AppContext doesnt work like it did was on my JSX:
App.JSX :
export interface ContextType {
cursor: {x: number, y: number},
}
export const AppContext = createContext<ContextType | null>(null);
export default function App() {
const [ cursor, setCursor ] = useState<ContextType['cursor']>({ x: -100, y: -100 }); // Store the cursor x and y position
...
return(
<div id="app" onMouseMove={ updateCursor }>
<AppContext.Provider value={{ cursor }}>
...
Cursor.JSX :
import { AppContext, ContextType } from "../../App;
...
export default function Cursor() {
const { cursor } = useContext(AppContext);
So it did say, Property ‘cursor’ does not exist on type ‘ContextType | null’.
3
Answers
It is because the property
cursor
does not exist on the typenull
(the initial context value set by your code when you called createContext), even though it exists inContextType
.One way to fix it is to change:
export const AppContext = createContext<ContextType | null>(null);
to
export const AppContext = createContext<ContextType>({ x: 0, y: 0 });
The above will make the context always have a
ContextType
-compliant valueAlternatively, you can still
useContext(AppContext)
, but you will need to check whether that value is null first. Probably something along the lines:The problem is the definition of the type in the
createContext
, because you also allownull
as value, which is not an object with a propertycursor
.I would define the context with a valid default fallback, e.g.
You’ll probably don’t call
useContext
outside of the ContextProvider, so the value will never be used. But doing it like this, it’s guaranteed, that a valid context object is returned.As an alternative define a special
useAppContext
method to access the context. This also improves readability.A clean and scalable way to do this is to separate this logic in a separate file and define what information will be passed by your application.
For example, I will leave an example of a code that I implemented in an authentication context that I believe could help you. In it, I also use Typescript.
File: /contexts/auth.tsx
File: /App.tsx
So, you can access the information inside something that is wrapped by the AuthProvider as follows:
File: /routes/index.tsx
Try applying this to your logic and it will certainly work, as well as improving the quality of your code.