1

I created a Zustand Store with Persist so

import create from 'zustand';
import { devtools, persist } from 'zustand/middleware';

import Router from 'next/router';

import { getAuth, signInWithEmailAndPassword } from 'firebase/auth';

import { query, collection, getDocs } from 'firebase/firestore';

import { toast } from 'react-hot-toast';

import { firestoreDb } from 'src/libs';
import { AppState, Admin } from 'src/types';

export const useAppStore = create<AppState>()(
  devtools(
    persist(
      (set) => ({
        crimes: [],
        isLoadingCrime: false,
        isLoadingUser: false,
        user: null,
        
       // Methods
        fetchCrimes: async () => {
          set((state) => ({ isLoadingCrime: (state.isLoadingCrime = true) }));
          const crimeQuery = query(collection(firestoreDb, 'crimes'));
          await getDocs(crimeQuery)
            .then((snapshot) => {
              set((state) => ({
                isLoadingCrime: (state.isLoadingCrime = false),
              }));
              set((state) => ({ crimes: (state.crimes = snapshot?.docs) }));
            })
            .catch((err) => {
              set((state) => ({
                isLoadingCrime: (state.isLoadingCrime = false),
              }));
              console.log(err);
            });
        },
      }),
      {
        name: 'app-storage',
      }
    )
  )
);

My Dashboard fetches the Crime from a function in the store called fetchCrime

import {
  ...
} from '@chakra-ui/react';
import Head from 'next/head';
import { useEffect } from 'react';

import AllCrimesTab from 'src/components/AllCrimesTab/AllCrimesTab';

import { useAppStore } from 'src/store';

const Dashboard = () => {
  const { fetchCrimes } = useAppStore();

  useEffect(() => {
    fetchCrimes();
  }, []);

  return (
    <Container maxWidth={'container.lg'}>
      <Head>
        <title>Crime-Report | Admin</title>
        <meta name="crime-report" content="Report any crime.." />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <HStack py={4}>
        <Heading fontSize={'xl'} fontWeight={'black'}>
          CrimeReport.
        </Heading>
        <Badge colorScheme={'purple'} rounded={'lg'}>
          Admin
        </Badge>
        <Spacer />
        <HStack>
          <Menu>
            <MenuButton>
              <Avatar name="Admin Report" size={'sm'} />
            </MenuButton>
            <MenuList>
              <MenuItem>
                <Text>admin@crime-report.com</Text>
              </MenuItem>
            </MenuList>
          </Menu>
        </HStack>
      </HStack>

      <Box mt={7}>
        <Tabs variant={'soft-rounded'} colorScheme={'purple'}>
          <TabList>
            <Tab fontSize={'sm'}>All Crimes</Tab>
            {/* <Tab fontSize={'sm'}>Attended Crimes</Tab> */}
          </TabList>
          <TabPanels>
            <TabPanel>
              <AllCrimesTab /> // This components renders the Tab Below
            </TabPanel>
          </TabPanels>
        </Tabs>
      </Box>
    </Container>
  );
};

export default Dashboard;

I have my AppState like this

export type AppState = {
  user: User | null;
  crimes: QueryDocumentSnapshot<DocumentData>[] | [];
  isLoadingCrime: boolean | undefined;
  isLoadingUser: boolean | undefined;
  fetchCrimes: () => void;
  loginAdmin: (user: Admin) => void;
};

// AllCrimesTab

import {
  ...
} from '@chakra-ui/react';

import { useAppStore } from 'src/store';

const AllCrimesTab = () => {
  const { isLoadingCrime, crimes } = useAppStore();

  return (
    <TableContainer border={'1px solid #EDF2F7'} rounded={'lg'}>
      <Table variant="striped">
        <TableCaption>CrimeReport. Data</TableCaption>
        {isLoadingCrime ? (
          <Thead p={4}>
            <Tr>
              <Th>
                <Center>
                  <Spinner emptyColor="gray.200" color="purple.500" />
                </Center>
              </Th>
            </Tr>
          </Thead>
        ) : (
          <Thead>
            <Tr>
              <Th>Email Address</Th>
              <Th>Name</Th>
              <Th>Phone Number</Th>
              <Th>Crime</Th>
            </Tr>
          </Thead>
        )}
        <Tbody>
          {crimes &&
            crimes?.map((crime) => (
              <Tr key={crime?.id}>
                <Td>{crime?.data().email}</Td>
                <Td>{crime?.data().name}</Td>
                <Td>{crime?.data().phoneNumber}</Td>
                <Td>{crime?.data().crime}</Td>
              </Tr>
            ))}
        </Tbody>
      </Table>
    </TableContainer>
  );
};

export default AllCrimesTab;

On mounting the component, I get this error:

 There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

If I remove the persist on the store, it usually works.

I understand this is a conflict in the SSR sie of next, but I need a way to get this work.

Any help is appreciated.

juliomalves
  • 42,130
  • 20
  • 150
  • 146
AbdulAzeez Olanrewaju
  • 976
  • 1
  • 13
  • 32
  • See my answer here: https://stackoverflow.com/questions/72649255/nextjs-zustand-persist-state/73705292#73705292 – TD1 Sep 13 '22 at 15:07

0 Answers0