Home > Net >  how do I convert my componentDidMount function to async componentDidMount type
how do I convert my componentDidMount function to async componentDidMount type

Time:12-06

This is my newsapp and this my News.js file of component folder

import React, { Component } from 'react'
import NeswItem from './NewsItem'

export class News extends Component {
  constructor(){
    super();
    this.state={
      data : null,
loading : false
    }
  }


  componentDidMount(){
    let url = //your news api url
    fetch(url).then((res)=>{
        res.json().then((result)=>{
            console.log(result.articles)
            this.setState({data:result.articles})
        })
    })
}

  render() {
    return (
      <>
      
    <div className="container my-3">
      
      <h2>Top Headlines</h2>
      <div className='row'>
        {this.state.data ?
        this.state.data.map((element)=>
           <div className="col-md-4" key={element.url} >
        <NeswItem title={element.title?.slice(0, 45)} description={element.description?.slice(0, 88)} imgurl={element.urlToImage} newsUrl={element.url}/>
        </div>
        )
        : null
        }
        
      </div>

      </div>
      </>
    )
  }
}

export default News


I am creating a react app to show latest news and this is my App.js file

import './App.css';

import React, { Component } from 'react'
import Navbar from './components/Navbar';
import News from './components/News';


export default class App extends Component {
  render() {
    return (
      <>
   
        <News/>
      
      </>
    )
  }
}

and this is my NewsItem.js file from component folder

import React, { Component } from 'react'

export class NeswItem extends Component {
  render() {
    let {title, description, imgurl,newsUrl}= this.props;

    return (
     
      <div>
        <div className="card my-3" style={{width: "18rem"}}>
  <img src={!imgurl?"https://img.etimg.com/thumb/msid-96022092,width-1070,height-580,imgsize-60058,overlay-economictimes/photo.jpg":imgurl} className="card-img-top" alt="..."/>
  <div className="card-body">
    <h5 className="card-title">{title}...</h5>
    <p className="card-text">{description}... </p>
    <a href={newsUrl} target="_blanck" className="btn btn-primary">Read more</a>
  </div>
</div>
      </div>
    )
  }
}

export default NeswItem

I want to convert my componentDidMount function into async componentDidMount one but I was unable to do it. note: I am using my api from newsapi.org

CodePudding user response:

Just use async keyword before componentDidMount

 async componentDidMount(){
    let url = //your news api url
    let res = await fetch(url)
    let data = await res.json()
    //rest of your code
}

CodePudding user response:

You cannot behave componentDidMount asynchronously, and what you did now is ok if you want to show loading before recieving data you can use your loading state that you already defined

here is sample :

  componentDidMount(){
    this.setState({loading:true})
    let url = //your news api url
    fetch(url).then((res)=>{
        res.json().then((result)=>{
            console.log(result.articles)
            this.setState({data:result.articles,loading:false})
        })
    })

and in jsx :

  <div>
        {
          this.state.loading ? 'loading...' : null
        }
      </div>

CodePudding user response:

I want to convert my componentDidMount function into async componentDidMount one

If you did that, it would be misleading. React calls componentDidMount and completely ignores any return value it provides. So if you made it async, it would return a promise that wouldn't be used by anything.

Instead, either do what you're doing (but handle errors), or write an async function to do it and call that function (while handling errors).

The first option:

componentDidMount() {
    let url = "your news api url";
    fetch(url)
        .then((res) => {
            if (!res.ok) {
                throw new Error(`HTTP error ${res.status}`);
            }
            return res.json();
        })
        .then(({articles}) => {
            console.log(articles);
            this.setState({ data: articles });
        })
        .catch((error) => {
            // ...handle/report error...
        });
}

The second:

async #getArticles() {
    let url = "your news api url";
    const res = await fetch(url);
    if (!res.ok) {
        throw new Error(`HTTP error ${res.status}`);
    }
    const { articles } = await res.json();
    console.log(articles);
    this.setState({ data: articles });
}
componentDidMount() {
    this.#getArticles().catch((error) => {
        // ...handle/report error...
    });
}

(I've also added a check of res.ok, since your code was falling prey to the footgun in the fetch API that I describe here. fetch only rejects its promise on network errors, not HTTP errors like 404 or 500.)

  • Related