Reputation: 13298
In my component, I need to fetch contestDetails
, get a value from the response (draftgroupId
), and then fetch the draftGroup
. Normally I'd wrap them each in useEffect
:
const [draftGroupId, setDraftGroupId] = useState();
useEffect(() => {
api.getContestDetails(contestId).then(res => setDraftGroupId(res.draftGroupId));
}, []);
useEffect(() => {
api.getDraftGroupId(draftGroupId).then(res => /* use the response */);
}, [draftGroupId]);
However, I'm making my fetches with RTK Query, so fetches themselves are performed with hooks. RTK Query handles when to fetch and when not to (or something like that), so the first query, useGetContestByIdQuery(contestId);
can just be at the top level of the component.
The second query, useGetDraftGroupByIdQuery(draftGroupId);
, however, needs to wait until we have a contestId
. But you can't call a hook conditionally, so I can't wrap it in an if
, and you also can't call a hook from another hook, so I can't wrap it in a useEffect
that would have contestId
as a dependency like the above example.
I'm not sure if this changes things, but I'm also not using the return value of the RTKQ hooks because I'm handling that data in my own RTK reducers (with extraReducers
). I don't think that makes a difference, since whether I get draftgroupId
from redux or whether I get it from the data
return of the query hook, my problem is still the same.
Here is what I came up with, which is simply wrapping each fetch in its own component, since the components will render conditionally.
const GetContest = ({ contestId, ...props }) => {
useGetContestByIdQuery(contestId); // populates state.currentDraft for next line
const { draftgroupId, gameTypeId } = useSelector(getCurrentDraftState).contest;
return !draftgroupId ? null : (
<GetDraftGroup
draftGroupId={draftgroupId}
gameTypeId={gameTypeId}
{...props}
/>
);
};
const GetDraftGroup = ({ draftGroupId, gameTypeId, ...props }) => {
useGetDraftGroupByIdQuery(draftGroupId, gameTypeId); // populates state.currentDraft.players for next line
const players = useSelector(getAllPlayers);
return !players ? null : <ActualGameScreen {...props} />;
};
This cannot possibly be the right way to do this, right? What is the right way to do this with RTK Query?
Upvotes: 0
Views: 745
Reputation: 44326
You can use the skip
option or skipToken
for your "conditional" case:
useGetContestByIdQuery(contestId ?? skipToken);
or
useGetContestByIdQuery(contestId, { skip: !contestId });
Upvotes: 1