简体   繁体   中英

React-Native: Type Error when parsing JSON

I was trying to implement a News App. It should show a list of news headlines on start with thumbnail image and description and then on clickinh the url should be opened in browser. But, i am stuck on halfway getting a Type Error.

Here are the codes of my NewsList and NewsDetail files.

NewsList.js

import React, { Component } from 'react';
import { ScrollView } from 'react-native';
import axios from 'axios';
import NewsDetail from './NewsDetail';

class NewsList extends Component {
    constructor(props) {
        super(props);

        this.state = {
          news: []
        };
    }
    //state = {news: []};
    componentWillMount() {
        axios.get('https://newsapi.org/v2/top-headlines?country=in&apiKey=MYAPIKEY')
        .then(response => this.setState({news: response.data }));
    }

    renderNews() {
        return this.state.news.map(newsData => 
        <NewsDetail key={newsData.title} newsData={newsData} />
     );

    }

    render() {
        console.log("something",this.state);
    return (
        <ScrollView>
            {this.renderNews()}
        </ScrollView>

    );
    }
}

export default NewsList;

NewsDetail.js

import React from 'react';
import { Text, View, Image, Linking } from 'react-native';
import Card from './Card';
import CardSection from './CardSection';
import Button from './Button';
import NewsList from './NewsList';

const NewsDetail =({ newsData }) => {
    const { title, description, thumbnail_image, urlToImage, url } = newsData;
    const { thumbnailStyle, 
        headerContentStyle,
        thumbnailContainerStyle,
        headerTextStyle,
        imageStyle } =styles;
 return(
     <Card>

         <CardSection>
             <View>
                 <Image 
                 style={thumbnailStyle}
                 source={{uri: urlToImage}}
                 />
             </View>
             <View style={headerContentStyle}>
                 <Text style={headerTextStyle}>{title}</Text>
                 <Text>{description}</Text>
             </View>
         </CardSection>

         <CardSection>
             <Image
             style={imageStyle} 
             source={{uri:urlToImage}}
              />
         </CardSection>

         <CardSection>
             <Button onPress={() =>Linking.openURL(url)} >
             ReadMore
             </Button>
         </CardSection>

     </Card>
 );
};



export default NewsDetail;

StackTrace of the Error i am getting

TypeError: this.state.news.map is not a function

This error is located at: in NewsList (at App.js:11) in RCTView (at View.js:78) in View (at App.js:9) in App (at renderApplication.js:35) in RCTView (at View.js:78) in View (at AppContainer.js:102) in RCTView (at View.js:78) in View (at AppContainer.js:122) in AppContainer (at renderApplication.js:34) NewsList.renderNews NewsList.js:21:31 NewsList.proxiedMethod createPrototypeProxy.js:44:29 NewsList.render NewsList.js:31:18 NewsList.proxiedMethod createPrototypeProxy.js:44:29 finishClassComponent ReactNativeRenderer-dev.js:8707:30 updateClassComponent ReactNativeRenderer-dev.js:8674:11 beginWork ReactNativeRenderer-dev.js:9375:15 performUnitOfWork ReactNativeRenderer-dev.js:11771:15 workLoop ReactNativeRenderer-dev.js:11839:25 Object.invokeGuardedCallback ReactNativeRenderer-dev.js:39:9

App.js

import React from 'react';
import { AppRegistry, View } from 'react-native';
import Header from './header';
import NewsList from './NewsList';

//create component
const App = () => {
    return(
    <View style={{ flex:0 }}>
        <Header headerText={'Headlines'} />
        <NewsList />
    </View>);
}

export default App;
AppRegistry.registerComponent('news', () => App);

The error you're getting - TypeError: this.state.news.map is not a function , means that news is not an array.
By checking your api response you should do:
this.setState({news: response.data.articles }) .

You can actually go to https://newsapi.org/v2/top-headlines?country=in&apiKey= "MY_API_KEY" in the browser or use a tool like curl or Postman to check what the response is. The data response is an object, but you need an array. articles is most likely the property you are after.

You may also want to check that this is an array and update what is displayed appropriately.

.then(response => {
  const news = response.data.articles;
  if (Array.isArray(news)) {
    this.setState({ news });
  } else {
    this.setState({ errorMessage: 'Could not load any articles' });
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM