Reputation: 25
I want to create a Dapp and am trying to add transaction tracking. For now, I want to show a modal window when an approval setting process starts. I try to change the modal isOpen state from inside the tanstack onMutate callback, but the state doesn't change and the modal doesn't appear. Here's the simplified version of the code:
Connection Options component - this is where the transaction starts and from where the modal should be opened.
import { useState } from "react";
import { useTrade } from "@/hooks";
function ConnectionOptions() {
const [tokenInAmount, setTokenInAmount] = useState(0);
const { onTrade } = useTrade();
const handleExecuteTrade = useCallback(() => {
onTrade(tokenInAmount);
}, [onTrade]);
return (
<Main>
<Button onClick={handleExecuteTrade}>
Trade
</Button>
<Modal />
</Main>
);
}
useTrade hook:
import { useCallback } from "react";
import { useAllowance, useApproval } from "@/hooks";
function useTrade() {
const { allowance = 0 } = useAllowance(); // Get the current allowance
const { setApproval } = useApproval();
const onTrade = useCallback(
async (tokenInAmount: number) => {
if (allowance < tokenInAmount) {
await setApproval();
return;
}
},
[allowance, setApproval]
);
return { onTrade };
}
export { useTrade };
useApproval hook:
import { useMutation } from "@tanstack/react-query";
import { useModal } from "@/hooks";
async function setTokenApproval(): Promise<void | null> {
// setting approval logic
}
}
function useApproval() {
const { handleOpenModal } = useModal();
const { mutateAsync: setApproval } = useMutation({
mutationFn: async () => await setTokenApproval(),
onMutate: () => {
console.log("Executed") // *** This part executes
handleOpenModal();
}
});
return { setApproval };
}
export { useApproval };
Modal component:
import Button from "@mui/material/Button";
import LibraryModal from "@mui/material/Modal";
import Box from "@mui/material/Box";
import { useModal } from "@/hooks";
function Modal() {
const { isOpen } = useModal();
return (
<LibraryModal open={isOpen}>
<Box sx={{ width: 200 }}>
<h2 id="child-modal-title">Text in a modal</h2>
</Box>
</LibraryModal>
);
}
export { Modal };
useModal hook
import { useCallback, useState } from "react";
function useModal() {
const [isOpen, setIsOpen] = useState(false);
const handleOpenModal = useCallback(() => setIsOpen(true), []);
const handleCloseModal = useCallback(() => setIsOpen(false), []);
return { isOpen, handleOpenModal, handleCloseModal };
}
export { useModal };
I tried move the state change outside from onMutate callback, but it still doesn't work. I also read react state documentation, but I couldn't figure out what's wrong with it.
Upvotes: 0
Views: 70
Reputation: 173
your hooks are not creating shared state across your app. for that, you would want to use a context or something similar. right now, each call of useModal() has its own state. try calling your hook once at the highest level component and passing isOpen, handleOpenModal, and handleCloseModal down through the child components through props. this may not be the structure you would like, but you can quickly see if that is your issue or not.
Upvotes: 1