.nickman
.nickman16mo ago

useMutation in useEffect dependency array causes infinite loop

I had a very unexpected issue today when testing out some code. I have a simple sum method in tRPC that accepts two numbers and returns the sum. I can change both of the number seperately in state and trigger the mutation every time I see a change in one of the two values (not an ideal way of handling this, but it is test code 😉 )
const [first, setFirst] = useState(0);
const [second, setSecond] = useState(0);
const [sum, setSum] = useState(0);
const sumMutation = trpcNext.events.sum.useMutation();

const handleFirstChange = useCallback(
async (event: ChangeEvent<HTMLInputElement>) => {
setFirst(+event.target.value);
},
[]
);
const handleSecondChange = useCallback(
async (event: ChangeEvent<HTMLInputElement>) => {
setSecond(+event.target.value);
},
[]
);

useEffect(() => {
debugger;
sumMutation.mutateAsync({ first, second }).then((result) => {
setSum(result.output);
});
}, [first, second/*, sumMutation*/]);
const [first, setFirst] = useState(0);
const [second, setSecond] = useState(0);
const [sum, setSum] = useState(0);
const sumMutation = trpcNext.events.sum.useMutation();

const handleFirstChange = useCallback(
async (event: ChangeEvent<HTMLInputElement>) => {
setFirst(+event.target.value);
},
[]
);
const handleSecondChange = useCallback(
async (event: ChangeEvent<HTMLInputElement>) => {
setSecond(+event.target.value);
},
[]
);

useEffect(() => {
debugger;
sumMutation.mutateAsync({ first, second }).then((result) => {
setSum(result.output);
});
}, [first, second/*, sumMutation*/]);
As you can see I commented out the sumMutation dependency in my useEffect, as adding this causes an infinite loop of calls to the tRPC server. It seems like this mutation is not a stable function and gets re-initialised every single render loop? Is this to be expected? I would assume you want this method to remain stable so it can actually be used inside of hook dependencies? Running on tRPC 10.32.0 right now with no customisation to reqct-query or anything, basic tRPC setup. (in next.js)
1 Reply
mark salsbery
mark salsbery16mo ago
sumMutation isn’t a function, it’s the return value of a call to useMutation It looks to me like the useEffect is redundant anyway…you should be able to mutate from your event handlers