0

I have a react component that I'm fetching data with to visualize.

The data fetching is happening constantly, instead of just once as is needed. I was wondering if there is a way to reduce this happening.

The component is like this,

export default function Analytics() {

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

  

  return (

I'm wondering if I should be using something like componentDidMount() here with componentDidUpdate() ?

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

There are different buttons to click on the site that can change the data requested, so I do want to be able to change the state of these data objects / request more, i.e., I filter the data based on dates. But confused how to stop it just constantly requesting data.

Thanks in advance,

Update to share the function being called.

export default function useAnalytics() {
  let d = new Date();
  d.setMonth(d.getMonth() - 1);
  const [dateRange, setDateRange] = useState([d.getTime(), Date.now()]);
  const [startDate, endDate] = dateRange;
  const { data: sentimentData } = useSWR(
    `dashboard/sentiment/get-sentiment-timefilter?startTime=${startDate}&endTime=${endDate}`,
    fetchSentiment
  );
  const { data: expressionsData } = useSWR(
    `dashboard/expression/get-expression-analytics?startTime=${startDate}&endTime=${endDate}`,
    apiRequest
  );
  return {
    sentimentData,
    expressionsData,
    overall,
    handleChange,
    setDateRange,
    sentimentStatistical,
    startDate,
    endDate,
  };
}

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;
      }
    });
}

With the answers,

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

This seems about right, I'm wondering how to substantiate the constants outside of useAnalytics?

juliomalves
  • 42,130
  • 20
  • 150
  • 146
LeCoda
  • 538
  • 7
  • 36
  • 79
  • 3
    `useAnalytics` is named like custom hook. Does it use `useEffect` inside or just call `fetch` several times? May be you can provide `useAnalytics` internals? – Fyodor Yemelyanenko Apr 18 '22 at 05:40
  • in your custom hook , did you have a useEffect ? if yes, did you have any deps in the effect while calling the api ? – Yassine CHABLI Apr 18 '22 at 06:05
  • _"The data fetching is happening constantly"_ - can you be more specific? When exactly is the data fetching happening? You're using `useSWR` to fetch the data, which by default has automatic revalidation enabled. To disable the auto-revalidation check out https://swr.vercel.app/docs/revalidation#disable-automatic-revalidations. – juliomalves Apr 19 '22 at 11:10

3 Answers3

1

First of all, You are using function component, here you cannot use ComponentDidMount() or ComponentDidUpdate() as they only work in class Components. You will have to use useEffect() but you haven't provided any additional code to understand the situation here.

Anyway if you are setting some state on button click when you fetch data and it is occurring again and again it's probably because you haven't used second argument on useEffect() which states that this useEffect() will only run when the second argument changes.

So to answer your question, pass second argument to useEffect() that you are setting when you click a button.

useEffect(() => {
    //
}, [state])
1

In the functional component we don't have componentDidMount() or componentDidUpdate () but we have the workaround for the same by using the useEffect react hook. For implementing the functionality of componentDidMount() we can utilize the following code snippet

useEffect(()=>{
 // this is the callback function that needs to be called only once (when the component has mounted) 
},[])

And for implementing the functionality of componentDidUpdate() we can utilize the following code snippet

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

As per your code it's functional component and you can't use componentDidMount() and componentDidUpdate() method as this functions are used in class component.

If you want prevent constantly updating component then there are different ways for both class and functional component.

  1. For Class Component: Only executes if old and new data doesn't match. this function does comparison between old and new value.

    componentDidUpdate(prevProps, prevState) { if (prevState.data !== this.state.data) { // Now fetch the new data here. } }

  2. For Functional Component: This is only execute when previous state change.

    useEffect(() => { // your data }, [stateName])