I am a junior developer working on an internal form application management system using NextJS 14. I am allowed to implement my own structure so I decided to use and try out zustand for state management for the first time. But I am extremely confused on how to structure and create zustand store.
The application involves three sequential forms/stages: submission, refinement, EOI (Expression of Interest). Each form must be completed and submitted in sequence before the next one becomes available. And there can be multiple applications, each with a unique name but sharing the same data structure and following the same process.
I learned that the most efficient way to handle this would be using SLICE PATTERNS. So I create 3 slices to represent each form and then put them in a central store. I also use localStorage to track each form and the entire application as well.
This is what I have tried so far
createSubmissionSlice:
import { persist, devtools } from "zustand/middleware";
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
const initialState = {
submissionChallengeTitle: "",
submissionChallengeStatement: "",
submissionChallengeLearning: "",
submissionBriefing: false,
submissionOrganisationName: "",
submissionOrganisationSector: "",
submissionOrganisationTraining: "",
submissionOrganisationProfile: "",
submissionOrganisationPartner: "",
submissionApplicantOrganisation: "",
submissionApplicantDesignation: "",
submissionApplicantUEN: "",
submissionApplicantOffice: "",
submissionSuccess: false,
submissionStatus: "Open",
submissionDeadline: "",
};
export const createSubmissionSlice = create(
devtools(
persist((set) => ({
...initialState,
updateSumissionData: (newData) =>
set((state) => ({ data: { ...state.data, ...newData } })),
saveSubmissionData: (newData) => set({ data: newData }),
setSubmissionSuccess: (value) => set({ submissionSuccess: value }),
setSubmissionDeadline: (value) => set({ submissionDeadline: value }),
})),
{
name: "submission-storage",
},
),
);
createRefinementSlice:
import { create } from "zustand";
import { persist, devtools } from "zustand/middleware";
const initialState = {
refinementChallengeTitle: "",
refinementChallengeStatement: "",
refinementChallengeLearning: "",
refinementBriefing: false,
refinmentOrganisationName: "",
refinementDeadline: ""
};
export const createRefinementSlice = create(
devtools(
persist((set) => {
...initialState,
updateRefinementData: (newData) =>
set((state) => ({ data: { ...state.data, ...newData } })),
saveRefinementData: (newData) =>
set((state) => ({ ...state.data, ...newData })),
setRefinmentDeadline: (value) => set({ submissionDeadline: value }),
};
}),
{
name: "refinement-storage",
},
),
);
createEOISlice:
import { persist, devtools } from "zustand/middleware";
import { create } from "zustand";
const initialState = {
eoiChallengeTitle: "",
eoiProposedSolution: "",
eoiLearningOutcome: "",
eoiSubmitterName: "",
eoiSubmitterOrganisation: "",
eoiSubmitterEmail: "",
eoiSubmitterPhone: "",
eoiSubmitterOffice: "",
eoiOrganisationUEN: "",
eoiOrganisationAddress: "",
eoiOrganisationProfile: "",
eoiFullTimeEmployees: "",
eoiAssociateEmployees: "",
eoiExpertiseArea: "",
eoiFamilarSector: "",
eoiOrganisationPorfolio: "",
eoiOrganisationWebsite: "",
eoiAwardWon: "",
eoiDeadline: "",
eoiSuccess: false,
}
export const createEoiSlice = create(
devtools(
persist((set) => ({
...initialState,
updateEoiData: (newData) =>
set((state) => ({ data: { ...state.data, ...newData } })),
saveEoiData: (newData) => set({ data: newData }),
eoiSuccess: false,
setEoiSuccess: (value) => set({ eoiSuccess: value }),
setEoiSuccessTrue: () => set({ eoiSuccess: true }),
// DATELINE
eoiDeadline: "",
setEoiDeadline: (value) => set({ eoiDeadline: value }),
})),
{
name: "eoi-storage",
},
),
);
useAppStore:
import { devtools, persist } from "zustand/middleware";
import { createSubmissionSlice } from "./cs-submission";
import { createEoiSlice } from "./cs-eoi";
import { createRefinementSlice } from "./cs-refinement";
import { create } from "domain";
export const useAppStore = create(
devtools(
persist(
(set) => ({
application: {},
addApplication: (appName) => {
set((state) => {
if (!state.applications[appName]) {
state.applications[appName] = {
submission: createSubmissionSlice(),
refinement: createRefinementSlice(),
eoi: createEoiSlice(),
};
}
});
},
}),
{
name: "app-storage",
getStorage: () => AsyncStorage,
},
),
),
);
I keep getting errors saying either TypeError: Cannot use ‘in’ operator to search for ‘getStorage’ in undefined or that the useAppStore is not a function. I think I got each slice set up right but I really don’t know how to put them together in the useAppStore. Could anyone offer advice and guidance on how to effectively organize and integrate these zustand slices into ‘useAppStore’ for managing multiple applications? Any advice/suggestion/insight would be gratefully appreciated! Please and thank you so much for your helps!
Julien Heng is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.