Search code examples
javascriptreact-nativefetch-apiredux-toolkitrtk-query

React Native Redux RTK Query returns null reponse. Similar solution works with Fetch API


First, I have implemented my solution with Fetch API which I have tested and it works. Then I came across Redux RTK Query and wanted to give it a try, but I get null as a response:

LOG response
LOG null
ERROR An unhandled error occurred processing a request for the endpoint "authenticateUser". In the case of an unhandled error, no tags will be "provided" or "invalidated". [TypeError: Cannot read property 'headers' of null]

Here is the solution with Fetch API ( works ):

const url = 'https://<cannotShowUrl>/Login?redirect=none';

const authenticate = (municipality, profileName, password) => {
  const form = {
    kommune: municipality,
    benutzername: profileName,
    passwort: password,
  };

  const urlencodedForm = Object.keys(form)
    .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(form[key])}`)
    .join('&');

  return fetch(url, {
    method: 'POST',
    headers: {
      Accept:
        'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: urlencodedForm,
  })
    .then((response) => response.headers.get('Set-Cookie'))
    .then((cookie) => {
      const ID = cookie.match(/ID=([^;]*)/)?.[1];

      if (!ID)
        throw new Error('Invalid credentials');

      return ID;
    })
    .catch((error) => {
      console.error(`Error during login: ${error.message}`);
      return error;
    });
};

export { authenticate };

I have tried to reimplement the same idea with RTK Query as following ( does not work ):

const url = '/Login?redirect=none';
export const loginApiSlice = createApi({
  reducerPath: 'loginApiSlice',
  baseQuery: fetchBaseQuery({ baseUrl: 'https://<cannotShowUrl>' }),
  endpoints: (builder) => ({
    authenticateUser: builder.mutation({
      query: (credentials) => {
        const form = {
          kommune: credentials.municipality,
          benutzername: credentials.profileName,
          passwort: credentials.password,
        };

        const urlencodedForm = Object.keys(form)
          .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(form[key])}`)
          .join('&');

        console.log(urlencodedForm);

        return {
          url,
          method: 'POST',
          headers: {
            Accept:
              'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
            'Content-Type': 'application/x-www-form-urlencoded',
          },
          body: urlencodedForm,
        };
      },
      transformResponse: (response) => {
        console.log('response');
        console.log(response);
        const cookie = response.headers.get('Set-Cookie');
        const ID = cookie?.match(/ID=([^;]*)/)?.[1];

        if (!ID) {
          console.log('error');
          throw new Error('Credentials are not valid');
        }

        return ID;
      },
      transformErrorResponse(response, meta, arg) {
        console.log('error');
        console.log(response);
      },
    }),
  }),
});

export const { useAuthenticateUserMutation } = loginApiSlice;

Versions of RN and Redux:

"@reduxjs/toolkit": "^1.9.5",
"react-redux": "^8.1.1",
"react-native": "0.71.11",

What am I doing wrong?


Solution

  • response in transformResponse is the fully parsed data, not the Response object you would have access to in fetch. It's actually called baseQueryReturnValue in the docs. You want to access the meta.response object in the second argument, meta. https://redux-toolkit.js.org/rtk-query/usage/customizing-queries

          transformResponse: (baseQueryReturnValue, meta) => {
            const cookie = meta.response.headers.get('Set-Cookie');
            const ID = cookie?.match(/ID=([^;]*)/)?.[1];
    
            if (!ID) {
              return null // never throw an error here!
            }
    
            return ID;
          },