I created context with null initial value that I am now accessing in other component. However when I destructure it to access the variables form the context then I get ts error:
Property 'users' does not exist on type 'GithubContextProps
function UserResults() {
const appContext = useContext(GithubContext)
const { users, loading, fetchUsers } = appContext
useEffect(() => {
fetchUsers()
}, [fetchUsers])
if (!loading) {
return (
<div className='grid grid-cols-1 gap-8 xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2'>
{users.map((user : User) => (
<UserItem key={user.id} user={user} />
))}
</div>
)
} else {
return <Spinner />
}
}
And here is where i created context:
export type User = {
id: number;
login: string;
avatar_url: string;
}
interface GithubContextProps {
users: User[];
loading: boolean;
fetchUsers: () => void;
}
const GithubContext = createContext<GithubContextProps | null>(null)
I tried solving this with using conditional checking whether appContext
is not null but then useEffect will throw errors that it cannot be used conditionally in this component. Any idea how to solve it without resorting to turning off React strict mode?
CodePudding user response:
How about:
const { users, loading, fetchUsers } = appContext ?? {};
You'll get undefined
when appContext is null
.
CodePudding user response:
try with
const GithubContext = createContext<GithubContextProps | null>({{ users:[], loading:false, fetchUsers:null }});
CodePudding user response:
useEffect
, and every other hook must always be called every time the component re-renders, so conditionally calling useEffect
will not work. I would try placing the check inside the useEffect
then place another check for our jsx:
useEffect(() => {
if (appContext) appContext.fetchUsers()
}, [fetchUsers])
if (!appContext || appContext.loading) return <Spinner />;
// you can then destructure
const { users, loading, fetchUsers } = appContext;
// ...
Or a more better solution, you can pass the context value as props to <UserResults />
instead so that you'll only need to check on the parent component, which is arguably more cleaner
const Parent = () => {
const appContext = useContext(GithubContext);
if (!appContext) return <Spinner />;
return <UserResults appContext={appContext} />;
}
const UserResults = ({ appContext }) => {
const { users, loading, fetchUsers } = appContext;
// ...
}