Passing Handlers or Centralize them?

I am using react-hook-form to create invoices with multiple modals for adding invoice items, applying discounts, updating information, and more. Each modal modifies the form state and requires specific handlers. Should I define all handlers in the parent component and pass them down to the child components, or should I create the handlers directly within the child components?
55 Replies
TechWitchTitan
TechWitchTitanā€¢4d ago
RHF exposes APIs like useFormContext, which are great for sharing form state across deeply nested components. You can combine this with Zustand or Context to handle specific actions (like adding items or applying discounts) without breaking RHF's state management.
ippo
ippoOPā€¢4d ago
@TechWitchTitan thanks for response I am using useFormContext for all my Form-Components to make them less noisy and verbose, but can I use them to pass custom functions?
TechWitchTitan
TechWitchTitanā€¢4d ago
Yuppers. For example, if you use Zustand, you can basically add prototypes on your store hook to do different things and then hook them into the context. Write it once, use it anywhere.
ippo
ippoOPā€¢4d ago
hmm...extra lib for that...let me think
TechWitchTitan
TechWitchTitanā€¢4d ago
I use Zustand a lot, so that is typically my go-to, But you can use the general context to do the same thing. The main advantage is that you can give access to the stores/useFormContext at a higher level in the component tree And for me, Zustand is perfect for carts what whatnot.
ippo
ippoOPā€¢4d ago
makes sense At the moment I have some complexity that I try to manage and I do not know what strategy I should pick for example I have an invoice form where you can add a lot of products and services The adding logic is in a modal Each item of your invoice has some other modals for giving discount and another modal for total discount My Form has tabs, each tab is a file, each file as some children at the moment I am using useFormContext in each child to manipulate the form state
TechWitchTitan
TechWitchTitanā€¢4d ago
Yeah, I would consolidate that into a useManageCart, and then all your modals/tabs have access
ippo
ippoOPā€¢4d ago
okay, now the thing is that each modal has its own state to be visible should this also be handled in a centralized manner? so modal state is "openModal" and each modal has handler like when you click OK or Changel
TechWitchTitan
TechWitchTitanā€¢4d ago
Something like that would probably take me about 10min to setup. So a bit longer for someone who has never used it. When it comes to modals, I always have a useModalStore. That way I can close it from anywhere after any GET/POST's
ippo
ippoOPā€¢4d ago
let me try to get a bigger picture šŸ™‚ do you have all your form handlers in a centralized "area" aka file? I am asking because this is what makes me a bit mad and is a bit uncomfortable: "ohh I have to change this state and handler logic, where is it again, let me see"
TechWitchTitan
TechWitchTitanā€¢4d ago
For example: src/utils/stores/[slice]. Where slice is any use[slice]. From there you wrap the top level component with the provider. Sometimes that is global, sometimes that is for the page, sometimes its just for a group of components. And if you wanna get super organized you can do something like: src/utils/[page/scope]/[slice]
ippo
ippoOPā€¢4d ago
feels very redux like
TechWitchTitan
TechWitchTitanā€¢4d ago
Zustand was to simplify context, and context was to simplify redux. The boilerplate is super minimal
import { create } from 'zustand'

const useBearStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}))
import { create } from 'zustand'

const useBearStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}))
Redux would be easily 3 or 4 times as much as that for ref
ippo
ippoOPā€¢4d ago
but what I have so far is something like this:
/views/Invoices
|__Form.tsx
|__options.countries.ts
|__validation.ts
|__Tab.Info.tsx
|__Tab.Foo.tsx
|__Tab.Bar.tsx
|__Positions.List.tsx
|__Modal.Add.Position.tsx
|__Modal.Discount.tsx
/views/Invoices
|__Form.tsx
|__options.countries.ts
|__validation.ts
|__Tab.Info.tsx
|__Tab.Foo.tsx
|__Tab.Bar.tsx
|__Positions.List.tsx
|__Modal.Add.Position.tsx
|__Modal.Discount.tsx
Form.tsx contains react-hook-form I would put that store in the Invoices folder, but let me see... your zustand-store, is it not redundant because of the store of react-hook-form? this is my component: https://paste.xinu.at/uD8yG/jsx
TechWitchTitan
TechWitchTitanā€¢4d ago
Depending on how extensible you want it to be, yes, it can be redundant.
ippo
ippoOPā€¢4d ago
I will rename it from SalesInvoiceItemsModal to ModalAddNewSalesInvoice let me ask you this first. You saw my component?
TechWitchTitan
TechWitchTitanā€¢4d ago
For you, I wouldnt store any values in it, I would use it to implement some custom logic before you send it to RHF
ippo
ippoOPā€¢4d ago
it is a little abstract, but you do agree that all state and all handler should be centralized, right šŸ™‚ ? (please say yes)
TechWitchTitan
TechWitchTitanā€¢4d ago
Im not home, so im not gonna open links I am not able to vette
ippo
ippoOPā€¢4d ago
let me paste the code here then
TechWitchTitan
TechWitchTitanā€¢4d ago
I would agree that centralizing logic is my go-to approach when feasable.
ippo
ippoOPā€¢4d ago
function SalesInvoiceItemsModal() {
// React Hook Form hooks
const { control, watch, setValue, getValues, setFocus } =
useRemixFormContext<SalesInvoiceFormValues>();

const { fields, append } = useFieldArray({
keyName: "rhf_id",
name: "pickedPositions",
control,
});

const [isModalOpen, setIsModalOpen] = useState(false);

// Derived values
const customerNo = watch("customerNo");
const paymentTerms = addDaysToDate(watch("paymentTerm"), watch("invoiceDate"));

// Modal handlers
const openModal = () => {
setIsModalOpen(true);
setFocus("invoiceItem");
};

const closeModal = () => {
setIsModalOpen(false);
setValue("pickedPositions", []);
};

const confirmPositions = () => {
setIsModalOpen(false);

const existingPositionIds = new Set(
getValues("positions").map((item) => item.productDetailId)
);

const updatedPositions = [
...getValues("positions"),
...getValues("pickedPositions").filter(
(item) => !existingPositionIds.has(item.productDetailId)
),
];

setValue(
"positions",
updatedPositions.map((position) => ({
...position,
quantity: 1,
price: String(position.price).replace(".", ","),
discountAmount: 0,
}))
);

setValue("pickedPositions", []);
};

const handleItemSelect = (selectedItem, clearCombobox) => {
if (!selectedItem) return;

const pickedPositionsIds = new Set(
getValues("pickedPositions").map((item) => item.productDetailId)
);

if (pickedPositionsIds.has(selectedItem.productDetailId)) {
clearCombobox();
return;
}

append(selectedItem);
clearCombobox();
};
function SalesInvoiceItemsModal() {
// React Hook Form hooks
const { control, watch, setValue, getValues, setFocus } =
useRemixFormContext<SalesInvoiceFormValues>();

const { fields, append } = useFieldArray({
keyName: "rhf_id",
name: "pickedPositions",
control,
});

const [isModalOpen, setIsModalOpen] = useState(false);

// Derived values
const customerNo = watch("customerNo");
const paymentTerms = addDaysToDate(watch("paymentTerm"), watch("invoiceDate"));

// Modal handlers
const openModal = () => {
setIsModalOpen(true);
setFocus("invoiceItem");
};

const closeModal = () => {
setIsModalOpen(false);
setValue("pickedPositions", []);
};

const confirmPositions = () => {
setIsModalOpen(false);

const existingPositionIds = new Set(
getValues("positions").map((item) => item.productDetailId)
);

const updatedPositions = [
...getValues("positions"),
...getValues("pickedPositions").filter(
(item) => !existingPositionIds.has(item.productDetailId)
),
];

setValue(
"positions",
updatedPositions.map((position) => ({
...position,
quantity: 1,
price: String(position.price).replace(".", ","),
discountAmount: 0,
}))
);

setValue("pickedPositions", []);
};

const handleItemSelect = (selectedItem, clearCombobox) => {
if (!selectedItem) return;

const pickedPositionsIds = new Set(
getValues("pickedPositions").map((item) => item.productDetailId)
);

if (pickedPositionsIds.has(selectedItem.productDetailId)) {
clearCombobox();
return;
}

append(selectedItem);
clearCombobox();
};
// Render
return (
<>
<Button theme="primary" onClick={openModal}>
Add New Product
</Button>
<Modal
isOpen={isModalOpen}
onCloseModal={closeModal}
onApplyModal={confirmPositions}
>
<ModalHeader>Add New Positions</ModalHeader>
<ModalBody>
<div className="w-[500px]">
<InvoiceItemCombobox
name="invoiceItem"
label="Product"
onItemSelectChange={handleItemSelect}
/>
<div className="mt-4 flex flex-col space-y-2">
{fields.map((item) => (
<div
className="border border-gray-400 p-1"
key={item.productDetailId}
>
<div className="font-bold">{item.name}</div>
<div>{item.serialNo}</div>
</div>
))}
</div>
</div>
</ModalBody>
</Modal>
</>
);
}


export default SalesInvoiceItemsModal;
// Render
return (
<>
<Button theme="primary" onClick={openModal}>
Add New Product
</Button>
<Modal
isOpen={isModalOpen}
onCloseModal={closeModal}
onApplyModal={confirmPositions}
>
<ModalHeader>Add New Positions</ModalHeader>
<ModalBody>
<div className="w-[500px]">
<InvoiceItemCombobox
name="invoiceItem"
label="Product"
onItemSelectChange={handleItemSelect}
/>
<div className="mt-4 flex flex-col space-y-2">
{fields.map((item) => (
<div
className="border border-gray-400 p-1"
key={item.productDetailId}
>
<div className="font-bold">{item.name}</div>
<div>{item.serialNo}</div>
</div>
))}
</div>
</div>
</ModalBody>
</Modal>
</>
);
}


export default SalesInvoiceItemsModal;
I guess you want to make each child component as dumb as possible, is that correct šŸ™‚ dumb in sense of "consumes state and does not contain any state logic"
TechWitchTitan
TechWitchTitanā€¢4d ago
I do my best to keep the lowest child dumb af šŸ¤£
ippo
ippoOPā€¢4d ago
I love that! okay, next question
TechWitchTitan
TechWitchTitanā€¢4d ago
The rumor is that parents and grand parents are supposed to be the smarter ones.
ippo
ippoOPā€¢4d ago
sure! like in real life if you look at my component, you would also centralize the state of this, right?
const [isModalOpen, setIsModalOpen] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false);
and give it a name like isAddInvoiceItemModalOpen
TechWitchTitan
TechWitchTitanā€¢4d ago
Personally, yes, I would move that into the useModalStore. That way I can keep track of the multiple modals and ensure that I will always have access to their controls. For example, if you have it so that when you have a multi-step modal workflow, when you close one then you can open the next at the same time. And that isolates functionality and makes components independent. From there, you can do all kinds of neat things. And you can share the discount modal between your add new product, and add new service. If you have something like that
ippo
ippoOPā€¢4d ago
could we first start with a global store, that contains all the state of the Invoice Form?
TechWitchTitan
TechWitchTitanā€¢4d ago
You "could" šŸ¤£
ippo
ippoOPā€¢4d ago
okay, because I am a bit overwhelmed with the complexity and do not have a clear picture
TechWitchTitan
TechWitchTitanā€¢4d ago
Careful with that global term
ippo
ippoOPā€¢4d ago
correct, global was not correct, I mean in the Invoice-Form context šŸ™‚
TechWitchTitan
TechWitchTitanā€¢4d ago
Global implies giving the whole src access, when you really want to slice it up
ippo
ippoOPā€¢4d ago
yep, very good catch! okay, did you see my folder/file structure?
TechWitchTitan
TechWitchTitanā€¢4d ago
I did
ippo
ippoOPā€¢4d ago
okay, just in case, I use this Form in a reusable manner Which means I create one Form that I can use in my Create and Update routes if there is data => update form if there is no data => create form in the end it is how the default state is set nothing special
TechWitchTitan
TechWitchTitanā€¢4d ago
And that is where zustand comes in handy. Because you can create a slice for invoice/create, invoice/update, invoice/[insert new thing] And then have invoice/[useStore] for anything that is shared between them
ippo
ippoOPā€¢4d ago
wait, this is still too advance for me and a little foggy and abstract, so lets look at this:
const SalesInvoicesForm = ({ salesInvoice }: SalesInvoiceFormProps) => {
const formMethods = useForm<SalesInvoiceFormValues>({
mode: "onTouched",
// --------------------- VALIDATION ---------------------
resolver: validation,
// ------------------------------------------------------
defaultValues: {
pickedPositions: [],
customerNo: "",
country: salesInvoice?.country ? salesInvoice.country : DEFAULT_COUNTRY,
paymentTerm: salesInvoice?.paymentTerm
? salesInvoice.paymentTerm
: DEFAULT_PAYMENT_TERM,
invoiceDate: salesInvoice?.invoiceDate,
contactId: salesInvoice?.contactId ?? "",
positions:
salesInvoice?.positions?.map((pos) => ({
...pos,
price: pos.price.toString().replace(".", ","),
})) ?? [],
},
});

// more stuff

}
const SalesInvoicesForm = ({ salesInvoice }: SalesInvoiceFormProps) => {
const formMethods = useForm<SalesInvoiceFormValues>({
mode: "onTouched",
// --------------------- VALIDATION ---------------------
resolver: validation,
// ------------------------------------------------------
defaultValues: {
pickedPositions: [],
customerNo: "",
country: salesInvoice?.country ? salesInvoice.country : DEFAULT_COUNTRY,
paymentTerm: salesInvoice?.paymentTerm
? salesInvoice.paymentTerm
: DEFAULT_PAYMENT_TERM,
invoiceDate: salesInvoice?.invoiceDate,
contactId: salesInvoice?.contactId ?? "",
positions:
salesInvoice?.positions?.map((pos) => ({
...pos,
price: pos.price.toString().replace(".", ","),
})) ?? [],
},
});

// more stuff

}
so we have our state for the Invoice there but no UI form state, like toggle state for modals or something in this Component, which is the parent component, there are also no handlers how would you add zustand in this case? (keep it very very very very very very simple so I can grasp the idea šŸ™‚ ) and how do you decide what to put in RHF-state management and what to put in zustand if I had to guess is: All data that is for the backend => RHF state Rest of data => zustand In my "Add new Invoice Position" Modal-Component, I have something like this:
const { control, watch, setValue, getValues, setFocus } =
useFormContext<SalesInvoiceFormValues>()


const { fields, append } = useFieldArray({
keyName: "rhf_id",
name: "pickedPositions",
control,
});


const createInvoiceIte, = () => {
// close the modal
setIsOpenModal(false);

// put data in form-state
setValue(
"positions",
combinedPositions.map((position) => {
position.quantity = 1;
position.price = String(position.price).replace(".", ",");
position.discountAmount = 0;

return position;
}),
);

// reset pickedPositions of modal, that you see before it
// is added in the form-state
setValue("pickedPositions", []);
};



// render logic, something like
{fields.map((item, index) => (
<div
className="border border-gray-400 p-1"
key={item.productDetailId}
>
<div className="font-bold">{item.name}</div>
<div>{item.serialNo}</div>
</div>
))}
const { control, watch, setValue, getValues, setFocus } =
useFormContext<SalesInvoiceFormValues>()


const { fields, append } = useFieldArray({
keyName: "rhf_id",
name: "pickedPositions",
control,
});


const createInvoiceIte, = () => {
// close the modal
setIsOpenModal(false);

// put data in form-state
setValue(
"positions",
combinedPositions.map((position) => {
position.quantity = 1;
position.price = String(position.price).replace(".", ",");
position.discountAmount = 0;

return position;
}),
);

// reset pickedPositions of modal, that you see before it
// is added in the form-state
setValue("pickedPositions", []);
};



// render logic, something like
{fields.map((item, index) => (
<div
className="border border-gray-400 p-1"
key={item.productDetailId}
>
<div className="font-bold">{item.name}</div>
<div>{item.serialNo}</div>
</div>
))}
TechWitchTitan
TechWitchTitanā€¢4d ago
import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';

type ModalTypes = 'none' | 'cart' | 'checkout' | 'success' | 'discount';


interface Modal {
type: ModalTypes;
status: boolean;
updateStatus: (status: boolean) => void;
}

interface ModalState {
modalOne: Modal;
modalTwo: Modal;
modalThree: Modal;
}

const useModalStore = create<ModalState>()(
devtools(
persist(
(set) => ({
modalOne: {
type: 'none',
status: false,
updateStatus: (status) => set((state) => ({ modalOne: { ...state.modalOne, status } })),
},
modalTwo: {
type: 'cart',
status: false,
updateStatus: (status) => set((state) => ({ modalTwo: { ...state.modalTwo, status } })),
},
modalThree: {
type: 'discount',
status: false,
updateStatus: (status) => {
set((state) => ({ modalThree: { ...state.modalThree, status } }));
// Update the react hook form with the discount
if (status) {
// Assuming you have a function to update the form from react hook form
updateDiscountForm({
discount: 10,
itemId: '123',
});
}
// Trigger a toast notification
showToast('Discount for item has been applied');
},
},
}),
{
name: 'modal-control',
},
),
),
);

function updateDiscountForm({ discount, itemId }: { discount: number; itemId: string }) {
// Implement the logic to update the react hook form with the discount
// This is a placeholder function and should be replaced with actual implementation
console.log('Updating discount form with new discount');
}

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

type ModalTypes = 'none' | 'cart' | 'checkout' | 'success' | 'discount';


interface Modal {
type: ModalTypes;
status: boolean;
updateStatus: (status: boolean) => void;
}

interface ModalState {
modalOne: Modal;
modalTwo: Modal;
modalThree: Modal;
}

const useModalStore = create<ModalState>()(
devtools(
persist(
(set) => ({
modalOne: {
type: 'none',
status: false,
updateStatus: (status) => set((state) => ({ modalOne: { ...state.modalOne, status } })),
},
modalTwo: {
type: 'cart',
status: false,
updateStatus: (status) => set((state) => ({ modalTwo: { ...state.modalTwo, status } })),
},
modalThree: {
type: 'discount',
status: false,
updateStatus: (status) => {
set((state) => ({ modalThree: { ...state.modalThree, status } }));
// Update the react hook form with the discount
if (status) {
// Assuming you have a function to update the form from react hook form
updateDiscountForm({
discount: 10,
itemId: '123',
});
}
// Trigger a toast notification
showToast('Discount for item has been applied');
},
},
}),
{
name: 'modal-control',
},
),
),
);

function updateDiscountForm({ discount, itemId }: { discount: number; itemId: string }) {
// Implement the logic to update the react hook form with the discount
// This is a placeholder function and should be replaced with actual implementation
console.log('Updating discount form with new discount');
}

export default useModalStore;
Here is a basic implementation of the modal store
ippo
ippoOPā€¢4d ago
use tsx after ``` for code highlighting šŸ™‚ did you read my questions šŸ™‚ ? let me know if you want to go to sleep or something we can do it when you have the time šŸ™‚
TechWitchTitan
TechWitchTitanā€¢4d ago
You guess is right. UI control and middlware I would put in zustand, and then the end result values would be stored in RHF Then when you are ready to update the DB, put that handler in the submit
ippo
ippoOPā€¢4d ago
thanks for this confidence boost šŸ˜„
TechWitchTitan
TechWitchTitanā€¢4d ago
That is what we are here for
ippo
ippoOPā€¢4d ago
okay, now there is one thing that I do not like you created a useModalStore why not create a useInvoiceUIStore ? WHY? to put all the UI state that is UI specific AND to put there all handler
TechWitchTitan
TechWitchTitanā€¢4d ago
You could do that if you wanted. But useInvoiceUIStore implies that you would put someting like tab control in there, when that is not something i would use Zustand for
ippo
ippoOPā€¢4d ago
šŸ¤”
TechWitchTitan
TechWitchTitanā€¢4d ago
But that is just me
ippo
ippoOPā€¢4d ago
please correct my if I am wrong when ever you can, I realy want to hear your opinion šŸ™‚ so I would have for each form a monster store, that contains all the UI state AND handlers WHY? to have one centralized area to look into
TechWitchTitan
TechWitchTitanā€¢4d ago
Nah, you would put things in the store that could/would reach into multiple components. You can think of it as this: If you would pass it down as a prop, then you can store it in zustand to make a quick hook.
ippo
ippoOPā€¢4d ago
nice rap! let me think... how does zustand communicates with RHF and uses its getters and setters for the state?
TechWitchTitan
TechWitchTitanā€¢4d ago
// Child Component (e.g., AddItemModal)
import { useFormContext } from 'react-hook-form';
import { useInvoiceStore } from './store';

const AddItemModal = () => {
const { setValue } = useFormContext();
const updateStatus = useInvoiceStore((state) => state.modalOne.updateStatus);
const status = useInvoiceStore((state) => state.modalOne.status);

const handleAddItem = (item) => {
updateStatus(false);
setValue('items', [...(getValues('items') || []), item]); // Update RHF form state
};

return (
<>
{status ? (
<div className="modal">
{/* Modal UI */}
<button onClick={() => handleAddItem({ name: 'New Item', price: 100 })}>
Add Item
</button>
</div>
) : null}
</>
);
};

export default AddItemModal;
// Child Component (e.g., AddItemModal)
import { useFormContext } from 'react-hook-form';
import { useInvoiceStore } from './store';

const AddItemModal = () => {
const { setValue } = useFormContext();
const updateStatus = useInvoiceStore((state) => state.modalOne.updateStatus);
const status = useInvoiceStore((state) => state.modalOne.status);

const handleAddItem = (item) => {
updateStatus(false);
setValue('items', [...(getValues('items') || []), item]); // Update RHF form state
};

return (
<>
{status ? (
<div className="modal">
{/* Modal UI */}
<button onClick={() => handleAddItem({ name: 'New Item', price: 100 })}>
Add Item
</button>
</div>
) : null}
</>
);
};

export default AddItemModal;
Something along these lines.
ippo
ippoOPā€¢4d ago
this is not centralized what I expected is something like this:
TechWitchTitan
TechWitchTitanā€¢4d ago
And then if someone qualifies for a discount, then you can pop up that from this modal.
// Child Component (e.g., AddItemModal)
import { useFormContext } from 'react-hook-form';
import { useInvoiceStore } from './store';

const AddItemModal = () => {
const { setValue } = useFormContext();
const updateStatus = useInvoiceStore((state) => state.modalOne.updateStatus);
const status = useInvoiceStore((state) => state.modalOne.status);
const updateDiscountStatus = useInvoiceStore((state) => state.modalThree.updateStatus);

const handleAddItem = (item) => {
updateStatus(false);
if (getsDiscount) {
updateDiscountStatus(true);
} else {
setValue('items', [...(getValues('items') || []), item]); // Update RHF form state
}
};

return (
<>
{status ? (
<div className="modal">
{/* Modal UI */}
<button onClick={() => handleAddItem({ name: 'New Item', price: 100 })}>
Add Item
</button>
</div>
) : null}
</>
);
};

export default AddItemModal;
// Child Component (e.g., AddItemModal)
import { useFormContext } from 'react-hook-form';
import { useInvoiceStore } from './store';

const AddItemModal = () => {
const { setValue } = useFormContext();
const updateStatus = useInvoiceStore((state) => state.modalOne.updateStatus);
const status = useInvoiceStore((state) => state.modalOne.status);
const updateDiscountStatus = useInvoiceStore((state) => state.modalThree.updateStatus);

const handleAddItem = (item) => {
updateStatus(false);
if (getsDiscount) {
updateDiscountStatus(true);
} else {
setValue('items', [...(getValues('items') || []), item]); // Update RHF form state
}
};

return (
<>
{status ? (
<div className="modal">
{/* Modal UI */}
<button onClick={() => handleAddItem({ name: 'New Item', price: 100 })}>
Add Item
</button>
</div>
) : null}
</>
);
};

export default AddItemModal;
There are hundreds of ways it can be done. So take what I offer with grains of salt.
ippo
ippoOPā€¢4d ago
// PSEUDO API
import { useCentralizedStore } from './store';

const AddItemModal = () => {
// importing centralized state and handler
const {isAddItemModalOpen, handleAddItem} = useCentralizedStore();

return (
<>
<Modal isOpen={isAddItemModalOpen}>
<div className="modal">
{/* Modal UI */}
<button onClick={handleAddItem}>
Add Item
</button>
</div>
</Modal>
</>
);
};

export default AddItemModal;
// PSEUDO API
import { useCentralizedStore } from './store';

const AddItemModal = () => {
// importing centralized state and handler
const {isAddItemModalOpen, handleAddItem} = useCentralizedStore();

return (
<>
<Modal isOpen={isAddItemModalOpen}>
<div className="modal">
{/* Modal UI */}
<button onClick={handleAddItem}>
Add Item
</button>
</div>
</Modal>
</>
);
};

export default AddItemModal;
is something like this possible? because what you have above is something what I have in a way
TechWitchTitan
TechWitchTitanā€¢4d ago
Let me think on that and i will get back to ya. I might try tinkering with it when I get back to my PC

Did you find this page helpful?