skip to Main Content

I am trying to build a website where there will be a header section where top headlines will be displayed and i am using news api to fetch the headlines and setting the fetched data as a state using componentdidmount()

but when i run the app i am getting this error:

Uncaught TypeError: Cannot read properties of undefined (reading 'backgroundImage')
    at NewsHeader.render (NewsHeader.js:30:1)
    at finishClassComponent (react-dom.development.js:19752:1)
    at updateClassComponent (react-dom.development.js:19698:1)
    at beginWork (react-dom.development.js:21611:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
    at invokeGuardedCallback (react-dom.development.js:4277:1)
    at beginWork$1 (react-dom.development.js:27451:1)
    at performUnitOfWork (react-dom.development.js:26557:1)
    at workLoopSync (react-dom.development.js:26466:1)

and this is my code :


import { Component } from 'react';

export default class NewsHeader extends Component {
  constructor() {
    super();
    this.state = {
      articles: [],
      loading: true,
      error: '',
    };
  }
  async componentDidMount() {
    try {
      let url = `https://newsapi.org/v2/top-headlines?country=in&apiKey=myapikey`;
      let data = await fetch(url);
      let parsedData = await data.json();

      if (parsedData.articles && parsedData.articles.length > 0) {
        this.setState({ articles: parsedData.articles, loading: false });
      } else {
        this.setState({ loading: false });
      }
    } catch (error) {
      console.error('Error fetching data:', error);
      this.setState({ loading: false, error: error.message });
    }
  }
  render() {
    let style = {};
    console.log(this.state.articles);
    if (this.state.articles.urlToImage) {
      style = {
        backgroundImage: `url(${this.state.articles.urlToImage})`,
      };
    } else {
      style = {
        backgroundImage: `url(https://images.unsplash.com/photo-1702957954496-8bba5d73a390?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D)`,
      };
    }
    return (
      <>
        <div
          className="container-fluid newshead-height newshead-background-image"
          style={style}
        >
          <div className="conatiner-fluid background-overlay newshead-height ">
            <h2 className="text-center pt-2 text-light">Top Headlines</h2>
            <h5>{this.state.articles.title}</h5>
            <p>{this.state.articles .description}</p>
          </div>
        </div>
      </>
    );
  }
}

Edit:

console:

data is getting printed on console

and if i try to access the data from the state in this way (this.state.articles[0].urlToImage) i am getting an error so i changed it to (this.state.articles.urlToImage) to show the output

2

Answers


  1. Chosen as BEST ANSWER

    I have tried all the methods I can think of but this is the only way that is working for me

    declaring individual variable's for all the data I need and getting the articles into a variable from the state and check for the data availability and assigning the data to the respective variable

    working page

            import { Component } from 'react';
        
        export default class NewsHeader extends Component {
          constructor() {
            super();
            this.state = {
              articles: [],
              loading: true,
              error: '',
            };
          }
          async componentDidMount() {
            try {
              let url = `https://newsapi.org/v2/top-headlines?country=in&apiKey=apikey`;
              let data = await fetch(url);
              let parsedData = await data.json();
        
              if (parsedData.articles && parsedData.articles.length > 0) {
                this.setState({ articles: parsedData.articles, loading: false });
              } else {
                this.setState((prevState) => {
                  return { ...prevState, loading: false };
                });
              }
            } catch (error) {
              console.error('Error fetching data:', error);
              this.setState({ loading: false, error: error.message });
            }
          }
          render() {
            let style = {};
            let articles = this.state.articles;
            let title = 'something went wrong ';
            let description = 'something went wrong';
            let backgroundImage =
              'https://images.unsplash.com/photo-1702957954496-8bba5d73a390?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D';
            if (articles.length >= 1) {
              if (articles[4].title) {
                title = articles[4].title;
              }
              if (articles[4].urlToImage) {
                backgroundImage = articles[4].urlToImage;
              }
              if (articles[4].description) {
                description = articles[4].description;
              }
            } else {
            }
            style = {
              backgroundImage: `url(${backgroundImage})`,
            };
            return (
              <>
                <div
                  className="container-fluid newshead-height newshead-background-image"
                  style={style}
                >
                  <div className="conatiner-fluid background-overlay newshead-height ">
                    <h2 className="text-center pt-2 text-light">Top Headlines</h2>
                    <h5 className="text-light">
                      <strong>{title}</strong>
                    </h5>
                    <p className="text-light">{description}</p>
                  </div>
                </div>
              </>
            );
          }
        }
    

    this is not the optimal way of getting it to work but this is the one that seems to be working in my case


  2. In cases where there is no data, you should keep the previous state or assign an empty array.

      if (parsedData.articles && parsedData.articles.length > 0) {
            this.setState({ articles: parsedData.articles, loading: false });
          } else {
            this.setState(prevState => {return {...prevState, loading: false }});
          }
    

    or empty array

    else {
            this.setState(prevState => {return {...prevState, articles:[],loading: false }});
          }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search