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?
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;
},