user13909231
user13909231

Reputation:

Not able to use value returned by React hook

I am trying to use a custom hook to make HTTP requests and then use a reducer to update the state in the component.

The hook runs correctly and I can get the response from the request but not able to use the response data in dispatch function.

Below is the code:

HTTP hook:

import React, { Fragment, useState, useEffect, useReducer } from 'react';
import axios from 'axios';

export const useHttpRequest = (initialData, initialURL) => {
  const [url, setUrl] = useState(initialURL);
  const [isError, setIsError] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      console.log('in a http hook');
      setIsError(false);
      try {
        const res = await axios(url);

        console.log(res);

        const responseData = res.data.data.data;
        return responseData;
      } catch (error) {
        setIsError(true);
      }
    };

    fetchData();
  }, [url]);

  return { isError, setUrl };
};

A function call in the state:


  const { isError, setUrl } = useHttpRequest();

  const getCategoryData = async () => {
    setLoading();
    try {
      const Data = await setUrl('/api/v1/category');

      dispatch({
        type: SET_CATEGORYDATA,
        payload: Data
      });
    } catch (err) {}
  };

A function call in components, where the function is passed through useContext

  useEffect(() => {
    getCategoryData();
  }, []);

Upvotes: 0

Views: 127

Answers (1)

HosseinAgha
HosseinAgha

Reputation: 833

  • You cannot await on a setState (setUrl) function.
  • You return in your fetch data which is not used later.

You need to first change your mindset on how you think in react hooks and when you need to use them.

As far as I understand you want to fetch some data from server, update the store on successful retrieval, and show an error when the request fails.

You should do this all the way or don't do this at all. You can put the dispatch in the hook or you can forget about the hook and write a reusable fetchData function and handle setHasError in your component's useEffect.

There are many ways to solve this but this is my preferred solution:

import React, { Fragment, useState, useEffect, useReducer } from 'react';
import axios from 'axios';

export const useHttpRequest = (url, updateStore) => {
  const [hasError, setHasError] = useState(false);

  const fetchData = async (url) => {
    setHasError(false);
    try {
      const res = await axios(url);
      const responseData = res.data.data.data;
      updateStore(responseData);
    } catch (error) {
      setHasError(true);
    }
  };

  useEffect(() => {
    if (url) {
      fetchData(url);
    }
  }, [url]);

  return { fetchData, hasError };
};
// in case you want to fetch the data on component render
const { fetchData, hasError } = useHttpRequest(url, (data) => dispatch({
  type: SET_CATEGORYDATA,
  payload: data
}));

// in case you want to fetch it in a callback
const clickButton = () => {
  fetchData(someCustomUrl);
}

Finally, you can generalize your dispatchers so you don't need to send the whole function to the hook and only send the dispatcher name.

Upvotes: 1

Related Questions