0

I want to make an API call with useSWR when navigation(route)'s params updates and store his value on a custom hook with contextAPI.

I have this component UsersPage that renders a list of users, it needs to have pagination, and when I click on some user, share his link based on his id and query requested (page, userId, nationality=nat, gender, etc).

I'm considering using useSWR for a better User Experience.

I tried

import { useUsers } from "../../hooks/useUsers";
import { useFetch } from "../../hooks/useFetch";

.
.
.

const { pageNumber, userId } = useParams();

const {
    selectedGender,
    nationality,
    results,
    showDetails,
    page,
    isAscending,
    toggleIsAscending,
    selectedUser,
    formattedName,
    formattedBirth,
    getQuery,
  } = useUsers();

useEffect(() => {

    const users = useFetch(getQuery());
//then update users state on useUsers Context's hook and render data on Context's child nodes
  }, [pageNumber]);

on custom hook useUsers the function getQuery is

  const getQuery = () => {
    const query = `&gender=${selectedGender}&nat=${nationality}&page=${page}&results=${results}`;

    return query;
  };

On useFetch hook I have:

import useSWR from "swr";

export function useFetch(query) {
  const API_URL = process.env.REACT_APP_API_URL;

  const fetcher = async (query) => {
    const FormedURL = `${API_URL}${query}`;

    const response = await fetch(FormedURL);
    const data = await response.json();

    return data.results;
  };
  const { data, error } = useSWR(query, fetcher);

  return { users: data, error };
}

I received: 'React Hook "useFetch" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.'

Have someone done this before and share your experience/advice?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

2 Answers2

0

I would try something like this :

const { pageNumber, userId } = useParams();

const {
    selectedGender,
    nationality,
    results,
    showDetails,
    page,
    isAscending,
    toggleIsAscending,
    selectedUser,
    formattedName,
    formattedBirth,
    getQuery,
  } = useUsers();

const { get, response } = useFetch(getQuery())

const fetchUsers = async () {
    const users = await get()
    if (response.ok){
        // sets users...
    }
}

useEffect(() => {
    fetchUsers()
}, [pageNumber]);
Kevin Gilbert
  • 903
  • 8
  • 21
0

There is no reason for you to use 3 separate hooks if all you are trying to accomplish is get a paginated list of users.

Hooks are reactive and can take inputs

Hooks are reactive by default, so if you pass a param to a hook and update the param, the hook will refresh.

const { users } = useUsers({ pageNumber });

This will give you updated list of users every time you change page number in your url (query params).

Simplifying your logic

  1. Build the query right inside useUsers and return it.
  2. Pass the query to useFetch and return data from SWR directly, you don't need to use get();
  3. This will allow you to get work done without a useEffect.

The structure of your useUsers hook is your personal preference. Remember to call the hooks inside