Integrating context code for Appwrite authentication with app router
Unanswered
larkx posted this in #help-forum
larkxOP
I followed the youtube guide (yt -> /watch?v=ZJOmaZaANkQ - links to youtube aren't allowed for some reason) and have struggled to convert the code over to app router.
I'm getting errors about the client component and using context and whatever.
I'm getting errors about the client component and using context and whatever.
1 Reply
larkxOP
Here's the error:
Here's my code for
I've wrapped the content in my layout.tsx file with the UserProvider.
Any ideas on how I could fix this? Any help is greatly appreciated ðŸ™
./src/hooks/user.tsx
Error:
× You're importing a component that needs createContext. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.
│ Learn more:
│
│
â•─[/Projects/my-app/src/hooks/user.tsx:3:1]
3 │ import { redirect } from 'next/navigation';
4 │ import {
5 │ useContext,
6 │ createContext,
· ─────────────
7 │ useEffect,
8 │ useState,
9 │ ReactNode,
╰────Here's my code for
user.tsximport { account } from '@/utils/appwrite';
import { AppwriteException, Models } from 'appwrite';
import { redirect } from 'next/navigation';
import {
useContext,
createContext,
useEffect,
useState,
ReactNode,
} from 'react';
export interface UserState {
user: Models.User<Models.Preferences> | null;
loading: boolean;
error: string | null;
logout: () => Promise<void>;
login: (email: string, password: string) => Promise<void>;
signup: (email: string, password: string, name: string) => Promise<void>;
}
const defaultState: UserState = {
user: null,
loading: true,
error: null,
logout: async () => {},
signup: async () => {},
login: async () => {},
};
const userContext = createContext<UserState>(defaultState);
type UserProviderProps = {
children: ReactNode;
};
export const UserProvider = ({ children }: UserProviderProps) => {
const [user, setUser] = useState<Models.User<Models.Preferences> | null>(
null
);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const loadAccount = async () => {
try {
const loadedAccount = await account.get();
setUser(loadedAccount);
} catch (error) {
console.error(error);
setError('failed to load user');
} finally {
setLoading(false);
}
};
const login = async (email: string, password: string) => {
console.log('Do you copy?')
try {
await account.createEmailSession(email, password);
await loadAccount();
redirect('/');
} catch (error: any) {
const appwriteException = error as AppwriteException;
console.error(appwriteException.message);
}
};
const signup = async (email: string, password: string, name: string) => {
try {
const session = await account.create('unique()', email, password, name);
setUser(session);
await account.createEmailSession(email, password);
redirect('/');
} catch (error) {
console.error(error);
}
};
const logout = async () => {
await account.deleteSession('current');
setUser(null);
redirect('/');
};
useEffect(() => {
loadAccount();
}, []);
return (
<userContext.Provider
value={{ user, loading, error, logout, login, signup }}
>
{children}
</userContext.Provider>
);
};
export const useUser = () => {
const context = useContext<UserState>(userContext);
return context;
};I've wrapped the content in my layout.tsx file with the UserProvider.
Any ideas on how I could fix this? Any help is greatly appreciated ðŸ™