0

I have a react component. If I user clicks on a Link To on the parent component they land on this child componented just fine. However if they refresh the page, or go to the link directly, their is no data, so I need to make an api call again myself for that unique id.

When I make the api call (when issue is undefined), it works, but I get a promise back that has fulfilled, with no data. How do I get the object?

class Issue extends React.Component {
       

            getIssue = async (id) => {
                try {
                    const endpoint = `https://api.github.com/repos/facebook/create-react-app/issues/${id}`;
                    const response = await fetch(endpoint);
                    const data = await response.json();
                    return data;
                } catch (error) {
                    console.log(error);
                }
            }
        
    
        // }
        render(){
            
            let { issue } = this.props.location;
            console.log(issue);
    
            if(issue === undefined){
                console.log('No Data');
                issue = this.getIssue(this.props.match.params.id);
                console.log(issue);
            } else {
                console.log('Data');
            }
    
            return (
            <h1>ff</h1>
                
            )
        }
    }
errata
  • 5,695
  • 10
  • 54
  • 99

4 Answers4

2

Rewrite your component to use state, rewrite getIssue to use Promise (it fits better here) and move it to componentDidMount method.

class Issue extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: null
    };
  }

  componentDidMount() {
    const id = this.props.match.params.id;
    const endpoint = `https://api.github.com/repos/facebook/create-react-app/issues/${id}`;

    fetch(endpoint)
      .then(response => response.json())
      .then(data => this.setState({ data }))
      .catch(err => console.log(err));
  }

  render() {
    return <h1>{this.state.data ? this.state.data.title : "Loading..."}</h1>;
  }
}
macborowy
  • 1,474
  • 10
  • 13
1

The reason is because your getIssue() is async function and it will return a promise which you have to handle later on. In your render() method you are not doing it, you have to use getIssue() with then() chained where you can get your data from promise:

render() {
  let { issue } = this.props.location;
  console.log(issue);

  if(issue === undefined) {
    console.log('No Data');
    this.getIssue(this.props.match.params.id)
      .then(response => {
        console.log(response);
      });
  } else {
    console.log('Data');
  }
  
  return (
    <h1>ff</h1>
  )
}
errata
  • 5,695
  • 10
  • 54
  • 99
  • 1
    The OP says that "I get a promise back that has fulfilled, with no data", so it seems like they know that `getIssue` is returning a promise, it's just that it doesn't resolve with any data... (I could be misinterpreting the issue though) – Nick Parsons Jul 25 '20 at 13:25
  • 1
    Yeah, I'm thinking exactly the same about misinterpreting now :) There's plenty of answers already, I hope one will be correct... – errata Jul 25 '20 at 13:27
1

You cannot call async functions during render() You should do async calls on a useEffect hook (if using hooks) or componentDidMount or one of the lifecycles of a React class.

An example:

class Issue extends React.Component {
  constructor() {
    this.state = {
      issue: null
    }
       
  componentDidMount() {
    const { issue } = this.props.location;
    if (!issue) {
      getIssue(this.props.match.params.id).then(data => {
        this.setState({ issue: data });
       }
    }
            
     getIssue = async (id) => {
                try {
                    const endpoint = `https://api.github.com/repos/facebook/create-react-app/issues/${id}`;
                    const response = await fetch(endpoint);
                    const data = await response.json();
                    return data;
                } catch (error) {
                    console.log(error);
                }
            }
        
    
        // }
        render(){
            
            let { issue } = this.state;
            console.log(issue);
    
            return (
            <h1>ff</h1>
                
            )
        }
    }
BravoZulu
  • 1,140
  • 11
  • 24
0

Two issues :

  1. Fetch usage - Just use the direct result and not the data as follows:

const url = 'https://api.github.com/repos/facebook/create-react-app/issues/20'

const getData = async () => {
  const data = await fetch(url);
  console.log(data)
}

getData();
  1. Using async in useEffect or componentDidMount - To use in useEffect you can refer this: How to call an async function inside a UseEffect() in React?
Karthik R
  • 5,523
  • 2
  • 18
  • 30