3

Somewhat new to React and hooks in React. I have a component that calls a communications hook inside of which a call to an API is made with AXIOS and then the JSON response is fed back to the component. The issue I'm having is the component is calling the hook like six times in a row, four of which of course come back with undefined data and then another two times which returns the expected JSON (the same both of those two times).

I did a quick console.log to double check if it was indeed the component calling the hook mulitple times or it was happening inside the hook, and it is the component.

How do I go about only have the hook called only once on demand and not multiple times like it is? Here's the part in question (not including the rest of the code in the widget because it doesn't pertain):

export default function TestWidget() {

//Fetch data from communicator
console.log("called");
const getJSONData = useCommunicatorAPI('https://jsonplaceholder.typicode.com/todos/1');

//Breakdown passed data
const {lastName, alertList, warningList} = getJSONData;

return (          
            <h1 id="welcomeTitle">Welcome {lastName}!</h1>

     );

}


export const useCommunicatorAPI = (requestAPI, requestData) => {

const [{ data, loading, error }, refetch] = useAxios('https://jsonplaceholder.typicode.com/todos/1', []);
console.log("data in Communicator:", data);

   return {data};
 }
4
  • We also need as much of the the etc...... that reproduces the problem. Please see minimal reproducible example. Commented Jun 8, 2020 at 21:09
  • I mean, I just added a little more but it's not really relevant. It's just a section to break down down the passed data into variables and then the rendering return. That's really the entire component, it's very simple. Commented Jun 8, 2020 at 21:17
  • 1
    Can you also show useCommunicatorAPI? Is that a 3rd party library? Commented Jun 8, 2020 at 21:19
  • Nope. Just a hook I wrote that contains an axios-hooks call. Added that as well, again nothing special to it. Commented Jun 8, 2020 at 21:24

3 Answers 3

2

I would use the useEffect hook to do this on mount and whenever any dependencies of the request change (like if the url changed).

Here is what you will want to look at for useEffect

Here is what it might look like:

const [jsonData, setJsonData] = React.useState({})
const url = ...whatver the url is
React.useEffect(() => {
  const doFetch = async () => {
    const jsonData = await callAxios(url, []);;
    setJsonData(jsonData)
  }
  doFetch();
}, [url])
...use jsonData from the useState

With the above example, the fetch will happen on mount and if the url changes.

Sign up to request clarification or add additional context in comments.

4 Comments

I had tried useEffect and got a compilation error stating I couldn't do a hook call from within it. Really weird. As far as using URL as a check, yeah that won't work as those are actually going to be encapsulated in the Communicator. The component (any component that calls the hook) just tells which API it wants to get the data from. I'll have to figure out something else then.
Got the same compilation error with your code above as last time I tried to use and effect on it: React Hook "useCommunicatorAPI" is called in function "doFetch" which is neither a React function component or a custm React Hook function.
You cannot use hooks inside useEffect. All this solution does is move the functionality out of the hook and into the component. If you want to do this request on 10 different components, using this solution you would have to re-write the code in a useEffect in each one. Not a good solution.
Updated to make the axios call not use hook language (use), that was confusing. It isn't actually a hook, just a function to call axios. If you want to do this request on 10 different components, just share the logic with a custom hook. The example was for this component, not for multiple components so the solution did not reflect that.
1

Why not just use the hook directly?

export default function TestWidget() {
 const [{ data, loading, error }, refetch] = 
useAxios('https://jsonplaceholder.typicode.com/todos/1', []);

  return (<h1 id="welcomeTitle">Welcome {lastName}!</h1>);
}

the empty array [] makes the hook fire once when called

1 Comment

Because this Communicator hook is eventually going to be used to create an abstraction layer whereby the calling component tells it which of the many different external APIs it wants to get data from. And I added the empty [] to try and cut down on the calls before I tracked it to the calling component.
0

Try creating a function with async/await where you fetch the data.

Here can you learn about it: https://javascript.info/async-await

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.