skip to Main Content

I have this Component:

/* eslint-disable */
import React, { useEffect, useState } from "react";
import { usePostValidateMutation } from "./features/apiSlice";

export const App = () => {
  const [postValidate] = usePostValidateMutation();

  const [token, setToken] = useState(undefined);

  useEffect(() => {
    const queryParameters = new URLSearchParams(window.location.search);
    const tokenParam = queryParameters.get("token");
    console.log(tokenParam);
    setToken(tokenParam);
    validate();
  }, []);

  const validate = async () => {
    await postValidate(token)
      .unwrap()
      .then((data) => console.log(data))
      .catch((error) => console.log(error));
  };

  return (
    <div className="container-fluid">
      <Stats />
    </div>
  );
};

export default App;

App is called with a token in querystring: http://localhost?token=a1b2c3.

I need to get that (short live) token and make an API call (Via RTK Query mutation) to get a long lived token.

My issue is that useEffect run twice and not once (I see two API call and twice printed token in console).

2

Answers


  1. One solution is to use a "query state" to wrap the call into a condition only when the query hasn’t been sent already.

    Something like

    import React, { useEffect, useState } from "react";
    import { usePostValidateMutation } from "./features/apiSlice";
    
    export const App = () => {
      const [postValidate] = usePostValidateMutation();
    
      const [token, setToken] = useState(undefined);
      const [hasRequestBeenSent, setHasRequestBeenSent] = useState(false);
    
      useEffect(() => {
        const queryParameters = new URLSearchParams(window.location.search);
        const tokenParam = queryParameters.get("token");
        console.log(tokenParam);
        setToken(tokenParam);
        if (!hasRequestBeenSent)
          validate();
      }, [hasRequestBeenSent]);
    
      const validate = async () => {
        await postValidate(token)
          .unwrap()
          .then((data) => console.log(data))
          .then(() => {
            setHasRequestBeenSent(true)
          })
          .catch((error) => console.log(error));
      };
    
      return (
        <div className="container-fluid">
          <Stats />
        </div>
      );
    };
    
    export default App;
    
    Login or Signup to reply.
  2. try to remove <React.StrictMode> from index.js file,

    ReactDOM.render(
      < React.StrictMode>
        <App />
      </React.StrictMode>,
      rootElement
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search