javascriptreactjsredux-toolkitrtk-query

RTK Query. Using mutation on component load causes infinite loop


I forgot how to work with React Redux, but now I work on a project, where we are introducing Redux and I try to implement server calls via modern Redux-Toolkit (RTK) Query mechanism. The problem is that I have to do a POST request not on a button click, how in the all examples, but once on a component rendering.

I do this:

import { useRef } from "react";
import { useMyPostMutation } from "src/api/apiSlice";

function AppMain() {  
  const [myPost, { isLoading, isError }] = useMyPostMutation();

  var temp = addNewDisplay(labelOfDisplay).unwrap();

  return (
    <main>
      ...
    </main>
  );
}

export { AppMain };

And I get the error:

Too many re-renders. React limits the number of renders to prevent an infinite loop.
at renderWithHooks

This works if I create a button and call the mutation when press it, but it is not what I need. How I can use the mutation this way?

It also works if I put it inside useEffect, but it a hook itself. Do I need to put into another hook?


Solution

  • Assuming that addNewDisplay actually supposed to be the myPost trigger function, then the issue is the unconditional dispatching of the trigger function. The component renders and dispatches the trigger function, which triggers the component to rerender with the updated endpoint/mutation data, and then again call the mutation trigger function, thus creating the render-loop issue you see.

    The trigger function is meant to be called in response to an event, e.g. a button is clicked or in your case the component mounted. Move the trigger function call into a useEffect hook call with appropriate dependency.

    Example:

    import { useMyPostMutation } from "src/api/apiSlice";
    
    function AppMain() {  
      const [myPost, { isLoading, isError }] = useMyPostMutation();
    
      useEffect(() => {
        myPost(somePayload).unwrap()
          .then(responseValue => {
            ....
          })
          .catch(error => {
            ...
          });
      }, [somePayload]);
    
      return (
        <main>
          ...
        </main>
      );
    }