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>
                
            )
        }
    }
3
  • if issue is undifined render a loading component . and make ur api call in componentDidMount() Commented Jul 25, 2020 at 13:18
  • How would I do that? Commented Jul 25, 2020 at 13:21
  • Do you see a valid id if you console.log(id) before your try in your getIssue method? Commented Jul 25, 2020 at 13:29

4 Answers 4

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>;
  }
}
Sign up to request clarification or add additional context in comments.

Comments

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

2 Comments

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)
Yeah, I'm thinking exactly the same about misinterpreting now :) There's plenty of answers already, I hope one will be correct...
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>
                
            )
        }
    }

Comments

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?

Comments