LeCoda
LeCoda

Reputation: 1016

useEffect and setState with hook function

I want to try and use react to fetch data efficiently using useEffect appropriately.

Currently, data fetching is happening constantly, instead of just once as is needed, and changing when there is a input to the date period (calling different data).

The component is like this,

export default function Analytics() {

  const {
    sentimentData,
    expressionsData,
    overall,
    handleChange,
    startDate,
    endDate,
    sentimentStatistical,
  } = useAnalytics();

  

  return (

UseAnalytics is another component specifically for fetching data, basically just a series of fetches.

i.e.,

export default function useAnalytics() {
....
const { data: sentimentData } = useSWR(
        `dashboard/sentiment/get-sentiment-timefilter?startTime=${startDate}&endTime=${endDate}`,
        fetchSentiment
      );
      ....
      return {
        sentimentData,
        expressionsData,
        overall,
        handleChange,
        setDateRange,
        sentimentStatistical,
        startDate,
        endDate,
      };
    }

Thanks in advance,

The apirequest is like this,

export async function apiRequest(path, method = "GET", data) {
  const accessToken = firebase.auth().currentUser
    ? await firebase.auth().currentUser.getIdToken()
    : undefined;
    //this is a workaround due to the backend responses not being built for this util.
  if (path == "dashboard/get-settings") {
    return fetch(`/api/${path}`, {
      method,
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${accessToken}`,
      },
      body: data ? JSON.stringify(data) : undefined,
    })
      .then((response) => response.json())
      .then((response) => {
        if (response.error === "error") {
          throw new CustomError(response.code, response.messages);
        } else {
          return response;
        }
      });
  }
  return fetch(`/api/${path}`, {
    method,
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
    body: data ? JSON.stringify(data) : undefined,
  })
    .then((response) => response.json())
    .then((response) => {
      if (response.status === "error") {
        // Automatically signout user if accessToken is no longer valid
        if (response.code === "auth/invalid-user-token") {
          firebase.auth().signOut();
        }

        throw new CustomError(response.code, response.message);
      } else {
        return response.data;
      }
    });
}

I think using useEffect here is the right approach. i.e.,

useEffect(()=>{
  // this callback function gets called when there is some change in the 
  // state variable (present in the dependency array)
},[state variable])

I'm confused about how to update the constants properly, something like this seems like one approach, but not sure about how I can use useEffect to update these variables properly, or if I should be doing this inside of useAnalytics?

i.e.,

const [analytics, setAnalytics] = useState({
    sentimentData: {},
    expressionsData: {},
    overall: {},
    handleChange: () => {},
    startDate: '',
    endDate: '',
    sentimentStatistical:{},
  });

  useEffect(()=>{
    // this callback function gets called when there is some change in the 
    // state variable (present in the dependency array)
  },[state variable])
  const {
    sentimentData,
    expressionsData,
    overall,
    handleChange,
    startDate,
    endDate,
    sentimentStatistical,
  } = useAnalytics();

Realised SWR is a hook, need to use SWR documentation :P

Upvotes: 0

Views: 99

Answers (1)

Rafael Abusleme
Rafael Abusleme

Reputation: 134

You have to store the requested information in states inside your custom hook. Then you could consume this hook wherever you want. This should work.

Define custom hook

const useAnalitycs  = () => {
  const [analytics, setAnalytics] = useState({
    sentimentData: {},
    expressionsData: {},
    overall: {},
    startDate: '',
    endDate: '',
    sentimentStatistical:{},
  });

  const handleChange = () => {
    /* */
  };

  useEffect(() => {
    const fetchData = async () => {
      // const response = await apiCall();
      // setAnalytics(...)
    };
    fetchData();
  }, []); // called once

  return {
    ...analytics,
    handleChange
  };
};

Consume useAnalytics hook

const ComponentConsumerA = () => {
  /* 
  const { state/methods you need } = useAnalytics()

  ...
  */
};

const ComponentConsumerB = () => {
  /* 
  const { state/methods you need } = useAnalytics()

  ...
  */
};

Upvotes: 2

Related Questions