Closed simonauner closed 1 year ago
Query accepts only one argument, as that would otherwise make useGetReportQuery
very problematic to write (you are passing period
in as options there, because options
are the fixed second argument).
Pass an object in instead:
getReport: builder.query({
query: ({group, period}) =>
`/group/${groupKey}/${period}`,
}),
useGetReportQuery({
group,
period
});
Ah, fantastic. Thanks!
Any idea how to do this with Typescript as the signature for it appears to be (method) query(arg: string): string | FetchArgs
so you cannot supply an object
@timhughes You need to specify the type. The signature is build.query<ReturnType, QueryArgument>({ ... })
Hi, I wanted to ask is there a way to include mutliple parameters plus an option ? I want to make a query where I need an id and a date to be pased in as parameters and a skip option to make the query conditional.
const [skipAppsQuery,setSkipApssQuery]= useState(true)
const tempDate="2022-12-25"
const {
data: apps,
isLoading: isAppsLoading,
isUninitialized:isAppsUninitialized,
isSuccess: isAppsSuccess,
isError: isAppError,
error: appError,
} = useRetrieveAppointmentsPublicQuery({id,tempDate},{skipAppsQuery})
retrieveAppointmentsPublic:builder.query({
query:({id,date="2022-12-25"})=>({
url:`/shops/public/appointments/${id}/${date}`,
method:'GET',
})
})
@KostasChili : I'm pretty sure that's just useRetrieveAppointmentsPublicQuery({id, date: tempDate}, {skip: skipAppsQuery})
Allthough you are right and I am really sorry for uploading invalid code, my problem is that the option skip is not executed. The query happens the moment the component mounts. I fixed this line of code (tempDate is now date) and the problem remains
@KostasChili I can confirm that if you pass {skip: true}
, the query will not run as long as it's still true
. So, there's got to be something about what you're passing in that's not matching expectations. Can you show the actual component?
I have completely removed the setSkipAppsQuery to make sure it will always be true as set in the useState. Thanks for the help and I apologize beforehand if this is something really simple.I am new to react and programming in general :)
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";
import { useParams, useNavigate } from "react-router-dom";
import { useGetShopQuery } from "../shops/shopsApiSlice";
import {
useMakeAppointmentMutation,
useRetrieveAppointmentsPublicQuery,
} from "../appointments/appointmentsApiSlice";
import { useEffect, useState } from "react";
import { Button, MenuItem, Typography } from "@mui/material";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DesktopDatePicker } from "@mui/x-date-pickers/DesktopDatePicker";
import { getDate, getMonth, getYear, format, addDays } from "date-fns";
export default function CreateAppointment() {
const navigate = useNavigate();
const [skipAppsQuery,setSkipAppsQuery] = useState(true);
const [name, setName] = useState("");
const [lastName, setLastName] = useState("");
const [canSelectDate, setCanSelectDate] = useState(false);
const [dateFormated, setDateFormated] = useState(addDays(new Date(), 1));
const [date, setDate] = useState("");
const [dateSubmitted, setDateSubmitted] = useState(false);
const [service, setService] = useState("");
const [canSelectTime, setCanSelectTime] = useState(false);
const [startTime, setStartTime] = useState("");
const [email, setEmail] = useState("");
const [comments, setComments] = useState("");
const { id } = useParams();
{
/* QUERIES */
}
const {
data: shop,
isLoading,
isSuccess,
isError,
error,
} = useGetShopQuery(id);
const [setAppointment, { isLoading: isAppLoading, isSuccess: isAppSuccess }] =
useMakeAppointmentMutation();
const tempDate="2022-12-25"
const {
data: apps,
isLoading: isAppsLoading,
isUninitialized:isAppsUninitialized,
isSuccess: isAppsSuccess,
isError: isAppError,
error: appError,
} = useRetrieveAppointmentsPublicQuery({id,date:tempDate},{skipAppsQuery})
{
/* END OF QUERIES */
}
useEffect(() => {
if ((name, lastName, email, service) !== "") {
setCanSelectDate(true);
}
}, [name, lastName, email, service]);
useEffect(() => {
if (dateSubmitted && date) {
// setCanSelectTime(true);
}
}, [dateSubmitted]);
if(isAppsSuccess)
{
console.log(apps)
}
{
/* FUNCTIONS FOR THE DATE PICKER - TODO The date Picker could be moved to a component of its own with all function needed */
}
const handleDateSubmit = (e) => {
setDateFormated(e);
setDate(
`${getDate(dateFormated)}-${getMonth(dateFormated) + 1}-${getYear(
dateFormated
)}`
);
setDateSubmitted(true);
};
function disableWeekends(date) {
return date.getDay() === 0 || date.getDay() === 6;
}
let availableSlots = null;
let occTimeSlots = null;
if (isAppsSuccess) {
occTimeSlots = apps.appList.map((ap) => {
return `${ap.startTime}-${ap.endTime}`;
});
availableSlots = apps.allTimeSlots.filter(
(item) => !occTimeSlots.includes(item)
);
}
const canSave =
[name, lastName, date, service, startTime, email].every(Boolean) &&
!isLoading;
{
/* FORM SUBMITION */
}
const handleAppSubmit = () => {
if (canSave) {
setAppointment({
id,
date,
service,
customerName: name + " " + lastName,
startTime: startTime.split("-")[0],
email,
comments,
});
}
setName("");
setLastName("");
setDate("");
setService("");
setStartTime("");
setEmail("");
setComments("");
navigate(`/shops/public/${id}/appsuccess`);
};
return (
<Box
component="form"
sx={{
"& .MuiTextField-root": { m: 1, width: "25ch" },
}}
noValidate
autoComplete="off"
>
<div>
<Typography variant="h6">
Καλώς ήρθατε στην σελίδα του καταστήματος {shop?.title}
</Typography>
<Typography>
Παρακαλώ συμπληρώστε τα παρακάτω στοιχεία για να κλείσετε το ραντεβού
σας
</Typography>
</div>
<div>
<TextField
id="name"
label="Ονομα"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<TextField
id="lastName"
label="Επίθετο"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
<TextField
id="email"
label="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<TextField
id="service"
label="Υπηρεσία"
value={service}
onChange={(e) => setService(e.target.value)}
/>
<TextField
id="comments"
label="Σχόλια Για το Ραντεβού σας"
multiline
maxRows={5}
value={comments}
onChange={(e) => setComments(e.target.value)}
/>
{/* DATE PICKER CONDITIONAL RENDERING */}
{canSelectDate ? (
<>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DesktopDatePicker
label="Ημερομηνία"
inputFormat="dd/MM/yyyy"
value={dateFormated}
onChange={handleDateSubmit}
shouldDisableDate={disableWeekends}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
</>
) : null}
{/* TIME PICKER CONDITIONAL RENDERING */}
{canSelectTime ? (
<>
<TextField
select
id="startTime"
label="Ωρα"
value={startTime}
selected
onChange={(e) => {
setStartTime(e.target.value);
}}
>
{availableSlots !== null ? (
availableSlots.map((slot) => {
return <MenuItem value={slot}>{slot}</MenuItem>;
})
) : (
<MenuItem>Δεν υπάρχουν διαθέσημα ραντεβού</MenuItem>
)}
</TextField>
</>
) : null}
</div>
<Button disabled={!canSave} onClick={handleAppSubmit} variant="contained">
Καταχωρηση Ραντεβου
</Button>
</Box>
);
}
@KostasChili : yeah, you're missing the actual skip
field :) It must literally be a field named skip
, exactly that, in the options object, and not skipAppsQuery
. It's okay if the state variable is named skipAppsQuery
, but you have to put that into the skip
options field. So, like I said, this is what you need:
useRetrieveAppointmentsPublicQuery({id,date:tempDate},{skip: skipAppsQuery})
Also, as a side note: setting state in a useEffect
is generally not a good approach. For example, you can calculate canSelectDate
as "derived" data there in the render logic, without any useState
or useEffect
:
@KostasChili I can confirm that if you pass
{skip: true}
, the query will not run as long as it's stilltrue
. So, there's got to be something about what you're passing in that's not matching expectations. Can you show the actual component?
I am sorry for wasting your time. Sometimes fatique can make as panic and make things more complicated than they really are. My problem is that I named the skip option as skipAppsQuery ...
Sorry for the inconvenience
No worries! I'd also recommend taking the time to read through the React beta docs pages to get more comfortable with some of the React-specific concepts, like the "Might Not Need an Effect" page I just linked.
for me am having trouble using multiple params on mutation${baseURL}/route/${id}
,{productId: productId},{headers: {authorization: ${token}
}
I am kindly asking for assistance configuring this mutation
postProduct: builder.mutation({
query: ({ userId, product, token }) => ({
url: `/product/${userId}`,
method: 'POST',
body: {
productId: `${product}`,
headers: { authorization: `${token}` },
},
}),
invalidatesTags: ['products'],
}),
@Big-Zude what is your question?
I am trying to use the RTK Query to make a mutation query to add a product to a user's account
The request I am trying to make is an axios POST request to the endpoint ${baseURL}/route/${id}, with a body containing the product ID and headers containing the authorization token.
axios.post(`${baseURL}/route/${id}`,{productId: productId},{headers: {authorization: ${token}})
However, when I try to use the RTK mutation query, It is not executing at all.
Here is the code I am using for the RTK mutation query:
postProduct: builder.mutation({
query: ({ userId, product, token }) => ({
url: `/product/${userId}`,
method: 'POST',
body: {
productId: `${product}`,
headers: { authorization: `${token}` },
},
}),
invalidatesTags: ['products'],
}),
Is this the correct way you use multiple params in a mutation or is there a better way of doing it? I would greatly appreciate any help in resolving this issue.
@Big-Zude what is your specific problem ? Does the use of the query generate an error on the front-end ? Does it generate an error no the back-end ? Edit : How are you using the mutation on your application ?
@Big-Zude what is your specific problem ? Does the use of the query generate an error on the front-end ? Does it generate an error no the back-end ? Edit : How are you using the mutation on your application ?
I managed to figure it out, I made a mistake on the headers part.
I am trying to use the RTK Query to make a mutation query to add a product to a user's account
The request I am trying to make is an axios POST request to the endpoint baseURL/route/{id}, with a body containing the product ID and headers containing the authorization token.
axios.post(`${baseURL}/route/${id}`,{productId: productId},{headers: {authorization: ${token}})
However, when I try to use the RTK mutation query, It is not executing at all.
Here is the code I am using for the RTK mutation query:
postProduct: builder.mutation({ query: ({ userId, product, token }) => ({ url: `/product/${userId}`, method: 'POST', body: { productId: `${product}`, headers: { authorization: `${token}` }, }, }), invalidatesTags: ['products'], }),
Is this the correct way you use multiple params in a mutation or is there a better way of doing it? I would greatly appreciate any help in resolving this issue.
This works for me, apologies for the unclear issue
postProduct: builder.mutation({
query: ({ userId, product, token }) => ({
url: `/product/${userId}`,
method: 'POST',
body: {
productId: `${product}`,
},
headers: { authorization: `${token}` },
}),
invalidatesTags: ['products'],
}),
From my understanding yes this is the correct way
Hi!
I started experimenting with the new RTK query and I must say I really enjoy being able to shave off all that boilerplate that used to be actions and reducers.
I have one question though to which I haven't found any examples or documentation on https://deploy-preview-1016--redux-starter-kit-docs.netlify.app ...
How to query with multiple parameters?
What I would like to do: service.js
export const myApi = createApi({ reducerPath: 'myApi', baseQuery: fetchBaseQuery({ baseUrl: '/api/v2/' }), endpoints: (builder) => ({ getReport: builder.query({ query: (group, period) => `/group/${groupKey}/${period}`, }), }), }); export const { useGetReportQuery } = myApi;
component.jsx
import { useGetReportQuery } from './service'; .... const { data: report, isLoading } = useGetReportQuery( group, period );
But it seems
period
is alwaysundefined
.I've modified the example here to show the issue https://deploy-preview-1016--redux-starter-kit-docs.netlify.app/usage/rtk-query/examples
https://codesandbox.io/s/rtk-query-demo-forked-bkvpw?file=/src/app/services/counter.ts
If you add a counter and open the sandbox console and increment you will see that it prints
$ query count hi undefined
I would expect it to print
$ query count hi hello
(see Counter.tsx:7)
I tried passing in the arguments to
useGetReportQuery
as an arrayuseGetReportQuery([group, period])
but that wasn't correct either :)What am I missing?
Hi,
Its really anoying why the RTK query accepts only one parameter. The only way out if for you to pass a single param of object as your props then destructure it inside your rtk query or call the key params directly
INSIDE YOUR COMPONENT CODE
const payload = {
data: {
email: signup?.data?.user?.email,
code: randNumber.toString(),
},
};
const params = {
id: id,
data: payload,
};
updateOTP(params)
.then((data) => {
// console.log({ data });
})
INSIDE YOUR RTK QUERY
updateOTP: builder.mutation({
query: (params) => ({
url: `${apiConfig.Onboarding.OTP}/${params.id}`,
method: "PUT",
body: params.data,
}),
}),
I'm having a trouble with skipping.
Here is the query:
class GetUsersOfGroup {
id: number;
skip: number;
take: number;
}
getUsersOfGroupByID: build.query<User[], GetUsersOfGroup>({
query: ({ id, ...query }) => ({
url: `/user/group/id/${id}/users`,
method: "GET",
params: query,
}),
}),
And here is how I call it:
const { data } = useGetUserGroupQuery(); // Get some data before fetching users
const { data: users } = useGetUsersOfGroupByIDQuery({ id: data?.id ?? skipToken, skip: 0, take: 30 }); // Here we should wait until we get data
The problem is that TypeScript only checks if the object I pass is skipToken
, but not its fields. Because of this I get: Type 'number | symbol' is not assignable to type 'number'
. Is there any workaround except // @ts-ignore
?
misclick 😅
Skip token is used in place of the entire argument, not as a property of it.
Skip token is used in place of the entire argument, not as a property of it.
Well, I can see that.
Is there any workaround except
// @ts-ignore
?
passing skip token as a property of your argument will not skip. that's why you're getting the error, because it won't work.
instead, use it in place of your argument, like i said.
const { data: users } = useGetUsersOfGroupByIDQuery(data?.id ? { id: data.id, skip: 0, take: 30 } : skipToken);
Hi!
I started experimenting with the new RTK query and I must say I really enjoy being able to shave off all that boilerplate that used to be actions and reducers.
I have one question though to which I haven't found any examples or documentation on https://deploy-preview-1016--redux-starter-kit-docs.netlify.app ...
How to query with multiple parameters?
What I would like to do: service.js
component.jsx
But it seems
period
is alwaysundefined
.I've modified the example here to show the issue https://deploy-preview-1016--redux-starter-kit-docs.netlify.app/usage/rtk-query/examples
https://codesandbox.io/s/rtk-query-demo-forked-bkvpw?file=/src/app/services/counter.ts
If you add a counter and open the sandbox console and increment you will see that it prints
I would expect it to print
(see Counter.tsx:7)
I tried passing in the arguments to
useGetReportQuery
as an arrayuseGetReportQuery([group, period])
but that wasn't correct either :)What am I missing?