7

I have a method getUrl() calling an API endpoint

  useEffect(() => {
    getUrl()
      .then(x => x.json())
      .then(x => {
        const { result } = x;
      });
  });

I can see in the Console the call in my page as you can see in the screenshot this is my data

{
   "result":"https://www.google.it",
   "error":null,
   "errorCode":null,
   "isSuccessful":true,
   "operationStatusCode":"OK"
}

How can I display the following result link example https://www.gooole.it in an external link in my view?

Do I have to use states?

I need an example of how to code to do this here

<a target="_blank" href={result}>Google Link</a>

enter image description here

AmerllicA
  • 29,059
  • 15
  • 130
  • 154
Koala7
  • 1,340
  • 7
  • 41
  • 83
  • 1
    Can you explain exactly what you want, I read over and over your question. but I don't understand exactly, do you need to call the `getUrl()` function after clicking the anchor? – AmerllicA Feb 24 '20 at 12:31
  • I think you need to store result in state. – waqas Mumtaz Feb 24 '20 at 12:32

5 Answers5

6

You have to use a state in your component :

const [url,setUrl] = useState('');

and render it :

<a target="_blank" href={url}>Google Link</a>

and in the use effect :

useEffect(() => {
   getUrl()
     .then(x => x.json())
     .then(x => {
        const { result } = x;
        // use set url hook 
        setUrl(result);
      });
  });
LHIOUI
  • 3,287
  • 2
  • 24
  • 37
  • 2
    I would advise to mention to add an empty array `[]` inside the `effect` to avoid calling api on every render. maybe he missed that. – awran5 Feb 24 '20 at 12:49
1

Do I have to use states?

Yes! you should use state object to maintain the fresh results as setState can be async and when you update the state a rerender takes place and UI gets updated. Check this:

Put this to initialize the state:

const [result, setResult] = useState({});

where result is a property and setResult will be the updater method.

Now you have to use it in the component's template such as :

{ result && <a target="_blank" href={result}>Google Link</a> }
{/* if result (its a promise) is not available when render happens then it might err. */}

Now in your useEffect:

useEffect(() => {
    getUrl()
      .then(x => x.json())
      .then(x => {
        const { result } = x;
        setResult(result); // <-----------set it here
      });
  },[result]); //<---pass it here it rerenders when state.result changes after first render.
Jai
  • 74,255
  • 12
  • 74
  • 103
1

One thing more I would like to suggest that making API calls in useEffect is not a good practice. React documentation also says to avoid the API calls in useEffect. Instead, create a function that will make the required API call and call that function in the useEffect.

const getUrl = () =>{
    /*make your API call here*/
}

useEffect(()=>{
    getUrl()
}
Rajiv
  • 3,346
  • 2
  • 12
  • 27
1

There are multiple ways to do that

First Usecase - will use useState

const [url,setUrl] = useState(''); //set useState

useEffect(() => {  //useEffect to get data on componentDidMount ans assign it to url
   getUrl()
     .then(x => x.json())
     .then(x => {
        const { result } = x;           
        setUrl(result); // placing data in useState
      });
  },[])

<a target="_blank" href={url}>Google Link</a>

Second Usecase - Declare one variable in your component and assign the response from api call to variable and used that

let url = ''
useEffect(() => {  //useEffect to get data on componentDidMount ans assign it to url
   getUrl()
     .then(x => x.json())
     .then(x => {
        url = x.result; //Assigning the result to url
      });
  },[])

<a target="_blank" href={url}>Google Link</a>
bajran
  • 1,433
  • 14
  • 23
0

I guess you should have separated file that contains all API calls:

// apiList.js

export const getUrl = (url, params) => axios.get(url, params).then(res => res.data);

etc

Then on your function component:

import React, { useEffect, useState } from 'react';
import { getUrl } from '[pathTo]/apiList';

const YourComponent = () => {
  const [state, setState] = useState({});
  useEffect(async () => {
    const result = await getUrl() || {};
    setState(result);
  }, []);


  return (
    <a target="_blank" href={state.result}>Google Link</a>
  );
};

On useEffect the call happens and the setState function changes the state of the component and the re-render will happen. then you see your a tag has a new value for its href attribute.

AmerllicA
  • 29,059
  • 15
  • 130
  • 154