Zustand
General idea
to fetch data on the server-side page by adding "use server"to the top of the function body and passing the fetched data to other client-side components like the UserStoreProvider component to handle states with Zustand.
Implementation
Firstly, Create create a store to handle our states for example we create useStore :
import { create } from 'zustand'
export const useStore = create(() => ({
user: null
}))
After creating the store we need a component to set our fetched data from server-side in the Zustand store on client-side, let's call it UserStoreProvider. Then we should pass fetched data on server-side as props to the initializer component.
'use client'
import { useStore } from '@/store/useStore'
export default function UserStoreProvider({ user, children }) {
useStore.setState({
user,
// ...
})
// ...
return children
}
'use server'
export default async function Page() {
const user = await getUser()
return (
<UserStoreProvider user={user}>
// ...
</UserStoreProvider>
)
}
Also you can import your fetching fucntions from the /lib/queries .
By using this architecture, we can incorporate every Next js server-side feature (like cookie) and after processing on server-side then render the app in client-side in order to store data in our state management like Zustand.
Data fetch from Zustand
Here is a structure of our store
export type UserGeneralData = {
userId: UserData['id'];
email: UserData['email'];
newEmail: string;
firstName: UserData['first_name'];
userName?: UserData['user_name'];
universityName: EducatorData['name'];
degreeProgramName?: DegreeData['name'];
universityId: UserData['university_id'];
degreeProgramId?: UserData['degree_program_id'];
lastName?: UserData['last_name'];
position?: UserData['position'];
department?: UserData['department'];
userType: CourseRole;
courseRole: CourseRole;
courseType: CourseType;
items: ItemSubset[] | ItemWithLink[];
exams: Exam[];
chapters: Chapter[];
};
Zustand stores can only be used in Client Components.
Basic example how to fetch data
export const runtime = 'edge';
export default async function Page() {
return <SelectComponent />
}
'use client';
import { useUserCourseStore } from '@/providers/UserCourseStoreProvider';
import { useUserStore } from '@/providers/UserStoreProvider';
export function SelectComponent() {
const { userId } = useUserStore((state) => state.userData);
const { userMaterial } = useUserCourseStore((state) => state.courseData);
const { items } = userMaterial;
//filter for a corresponding type
const lectures = items.filter((item) => item.type === 'lecture');
return ({
lectures.map((lecture) => (
<LectureItem
key={lecture.id}
lecture={lecture}
/>
))})
}