I am building a trivia app using the OpenTBD API.
I use SWR to make my API requests and get the questions and answers I want to display when my component renders
API call:
import useSWR from "swr";
export function useFetch(category, amount, difficulty) {
const url = `https://opentdb.com/api.php?amount=${amount}&category=${category}&difficulty=${difficulty}&type=multiple`;
const fetcher = (...args) => fetch(...args).then((res) => res.json());
const { data, error } = useSWR(url, fetcher, {
revalidateOnFocus: false,
});
return {
data: data,
isLoading: !error && !data,
isError: error,
};
}
Component :
function Quiz() {
const { category, color } = useSelector((state) => state.start);
const { amount, difficulty } = useSelector((state) => state.settings);
const gameEnded = useSelector((state) => state.end.isEnded);
const dispatch = useDispatch();
const { data, isLoading, isError } = useFetch(category, amount, difficulty);
if (isLoading) {
return <FlowerSpinner color={color} />;
}
if (isError) {
return <div>An error has occured.</div>;
}
dispatch(updateQuestions(createQuestions(data.results)));
return (
<>
<Questions />
{gameEnded ? <PlayAgainBtn /> : <VerifyButton />}
</>
);
}
export default Quiz;
This works fine but now, when the game is over, I have a "Play Again" button that's displayed and I'd like to add an on click to create a new fetch in order to get a new set of questions. I can't call the useFetch hook within a function like doing :
<button onClick={() => useFetch(newArgs)} />
so I tried to use mutate but I think because I am using the same url (the amount, category and difficulty doesn't change) when I call mutate, no new data is fetched
You could try conditional fetching which has worked for me before. I can't remember if it invalidates the cache of SWR but I recall it being the correct answer over mutate. My thought is that when you select the "Play Again" button, you could have a state such as
const [playAgain, setPlayAgain] = useState(false)
This gets passed to useFetch and you can structure useSWR like so:
const { data, error } = useSWR(playAgain ? url : null, fetcher, {
revalidateOnFocus: false,
});
You'll need to come up with a solution for the first playthrough but that very well could be another state to handle that.