Im converting an existing Reactjs project to typescript. Im also learning TS as I go on this project. I am getting a few errors that I am not sure how to navigate and cant seem to find a good answer on google.
One of my errors, I am pulling a useState boolean from my useContext into my protected route:
Property ‘loggedIn’ does not exist on type ‘{}’.
Protected Route:
import { Navigate } from "react-router-dom";
import { useAuthContext } from "../context/AuthContext";
import { ReactNode } from "react";
// type ProtectedRouteProps = {
// children: ReactNode;
// };
export const ProtectedRoute = ({ children }: any) => {
const { loggedIn } = useAuthContext();
if (!loggedIn) {
// user is not authenticated
return <Navigate to="/" />;
}
return children;
};
My AuthContext:
import { useState, createContext, useContext, ReactNode } from "react";
import { useNavigate } from "react-router-dom";
const AuthContext = createContext({});
export function useAuthContext() {
return useContext(AuthContext);
}
type AuthProviderProps = {
children: ReactNode;
};
export function AuthProvider({ children }: AuthProviderProps) {
const [loggedIn, setLoggedIn] = useState<boolean>(
localStorage.getItem("loggedIn") === "true"
);
const [selectedDogs, setSelectedDogs] = useState<number[]>([]);
const navigate = useNavigate();
function setDogMatch(data: number[]) {
setSelectedDogs(data);
navigate("/dog-match");
}
return (
<AuthContext.Provider
value={{
loggedIn,
setLoggedIn,
selectedDogs,
setDogMatch,
}}
>
{children}
</AuthContext.Provider>
);
}
Not sure what I am missing for that type and where it would need to be set if in my AuthContext or Protected Route.
I also created another error myself my SearchFilter.tsx. Error:
Property ‘map’ does not exist on type ‘string | number’.
Property ‘map’ does not exist on type ‘string’.
Heres my SearchFilter.tsx not sure what to do with that map type error. my SearchFilter.tsx takes in data from an API containing strings(dog breeds) and numbers(dog ids) i believe i have my types set up correct for that :
import Select from "react-select";
type Props ={
props: string | number
data: string | number
name: string
}
export default function SearchFilters(props: Props) {
const options =
props.data &&
props.data.map((data: Props) => {
return { value: data, label: data };
});
return (
<div className="dropdown-container">
<h4>{props.name}</h4>
<Select options={options} isSearchable={true} {...props} />
</div>
);
}
Thanks for the help new to TypeScript and learning as I go on this project!
2
Answers
1. Property ‘loggedIn’ does not exist on type ‘{}’.
2. Property ‘map’ does not exist on type ‘string | number’. Property ‘map’ does not exist on type ‘string’.
You’re calling
.map()
onprops.data
, which is of typestring | number
..map()
is only callable on objects which are iterable. Your SearchFilter.tsx is unclear about the exact type, so I’m only guessing.This will make this error go away, but may introduce another error somewhere else.
createContext
, which does not have aloggedIn
field.You could instead set the type explicitly through the generic parameter to
createContext
, e.g.createContext<T>(defaultVal)
. Alternatively, pass a default value that contains all the type information.props.data
should be an array, but you have typed it as either astring
or anumber
.