skip to Main Content
export const useLogin = (loginType) => {
  return useQuery({
    queryKey: ['login', loginType],
    // 'login' is simple function which use axios get method
    queryFn: async () => await login(loginType),
  });
};

const Login = () => {
  const [loginType, setLoginType] = useState('google');

  const { data } = useLogin(loginType);

  const onClickSocialLogin = (type) => {
    setLoginType(type);

    // I want to use data
  };
  
  return (
    <button onClick={() => onClickSocialLogin('google')}>Google Login</button>
    <button onClick={() => onClickSocialLogin('github')}>Github Login</button>
  )
}

When I click Google Login button, I want to use google login data in onClickSocialLogin function.
When I click Github Login button, I want to use github login data in onClickSocialLogin function.
But When I use data in onClickSocialLogin funtion, this data is old one. How can I fix it??

2

Answers


  1. The issue you’re facing is due to the asynchronous nature of the useQuery hook from React Query. When you call setLoginType(type), it updates the state and triggers a re-render. However, the data fetched by useQuery is not immediately available because the query is asynchronous. Thus, when you try to use data in the onClickSocialLogin function, it still holds the old data from the previous state.

    To solve this, you can use the onSuccess callback provided by useQuery. This callback is executed when the query successfully fetches new data. Here’s how you can modify your useLogin hook and Login component:

    Modified useLogin Hook

    export const useLogin = (loginType, onSuccess) => {
    return useQuery({
    queryKey: ['login', loginType],
    queryFn: async () => await login(loginType),
    onSuccess: onSuccess,
    });
    };
    

    The login component:

     const Login = () => {
     const [loginType, setLoginType] = useState('google');
    
     const onSuccess = (newData) => {
    // newData contains the latest data fetched by useQuery
    // You can use newData here as per your requirement
     };
    
     const { data } = useLogin(loginType, onSuccess);
    
     const onClickSocialLogin = (type) => {
      setLoginType(type);
    
       // Instead of using 'data' here, use it in the 'onSuccess' callback
      };
    
       return (
           <>
         <button onClick={() => onClickSocialLogin('google')}>Google 
          Login</button>
          <button onClick={() => onClickSocialLogin('github')}>Github 
          Login</button>
          </>
        );
        }
    

    This approach ensures that you have the latest data available in the onSuccess callback. You can handle the new data accordingly based on the type of login or any other logic you need. Remember, the onSuccess callback is only triggered after the new data is successfully fetched, so you won’t be dealing with stale data.

    Login or Signup to reply.
  2. Login should be mutation. It logs the user in, or creates a token. You don’t want to cache it. It’s also likely a POST request, so it’s a mutation.

    Mutations don’t have the problem because you can just fire them imperatively:

    export const useLogin = (loginType, onSuccess) => {
      return useMutation({
        mutationFn: login
      });
    }
    
    const { mutate } = useLogin()
    
    <button onClick={() => mutate('google')}>Google Login</button>
    <button onClick={() => mutate('github')}>Github Login</button>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search