React-NativeでNews一覧ページを作る

ReactNativeを使ってNews最新記事を表示するページを作ります。
※expo31.0.2利用

##完成イメージ

<img width="300" alt="スクリーンショット 2018-12-13 12.25.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/252667/5d5047db-d7c0-97d1-0cad-fe9572f89163.png">


**下にスワイプすると、spinnerが出てきて、最新記事を更新します。**
<img width="300" alt="Simulator Screen Shot - iPhone 8 Plus - 2018-12-12 at 13.33.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/252667/e9a8981d-3aa5-ba9b-a258-37b06daabdbb.png">


##下準備
###NEWS APIにサインアップする
[NEWS API](https://newsapi.org/)に登録して、無料API　keyを取得します。

###作業ディレクトリの作成、必要モジュールのインストール
```terminal:terminal
expo init NewsList
cd NewsList

npm install --save react-native-elements
npm install --save moment
npm install
```

###必要なファイルを作成
```
├── src
│   ├── components
│   │   └── Article.js
│   └── news.js
```
```terminal:terminal
mkdir src
cd src
touch src/news.js
mkdir components
touch components/Article.js
```

##各ファイルの記述
###news.js
NEWS APIからJSONを取得します。

```javascript:news.js
//YOUR_API_KEY_HEREに自分のAPI keyを入れてください
const url = "https://newsapi.org/v2/top-headlines?country=us&apiKey=YOUR_API_KEY_HERE";

export async function getNews() {
    let result = await fetch(url).then(response => response.json());
    return result.articles;
}
```

###App.js
News記事の読み込みについて書きます。

```javascript:App.js
import React from 'react';
import { FlatList } from 'react-native';

// Import getNews from news.js
import { getNews } from './src/news';
import Article from './src/components/Article';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { articles: [], refreshing: true };
    this.fetchNews = this.fetchNews.bind(this);
  }

  componentDidMount() {
    this.fetchNews();
  }

  fetchNews() {
    getNews()
      .then(articles => this.setState({ articles, refreshing: false }))
      .catch(() => this.setState({ refreshing: false }));
  }

  handleRefresh() {
    this.setState(
      {
        refreshing: true
      },
      () => this.fetchNews()
    );
  }

  render() {
    return (
      <FlatList
        data={this.state.articles}
        renderItem={({ item }) => <Article article={item} />}
        keyExtractor={item => item.url}
        refreshing={this.state.refreshing}
        onRefresh={this.handleRefresh.bind(this)}
      />
    );
  }
}
```


###Article.js
ニュース記事一覧の見た目の部分を書きます。
[参考記事](https://medium.freecodecamp.org/create-a-news-app-using-react-native-ced249263627)では、"TouchableNativeFeedback"と記載されていましたが、
Androidのみの対応になるので、"TouchableHighlight"でAndroidとiOS両方に対応させます。

```javascript:Article.js
import React from 'react';
import { View, Linking, TouchableHighlight } from 'react-native';
import { Text, Button, Card, Divider } from 'react-native-elements';
import moment from 'moment';

export default class Article extends React.Component {
  render() {
    const {
      description,
      publishedAt,
      source,
      urlToImage,
      url
    } = this.props.article;
    const { noteStyle } = styles;
    const time = moment(publishedAt || moment.now()).fromNow();
    const defaultImg =
      'https://wallpaper.wiki/wp-content/uploads/2017/04/wallpaper.wiki-Images-HD-Diamond-Pattern-PIC-WPB009691.jpg';

    return (
      <TouchableHighlight
        useForeground
        onPress={() => Linking.openURL(url)}
      >
        <Card
          image={{
            uri: urlToImage || defaultImg
          }}
        >
          <Text style={{ marginBottom: 10 }}>
            {description || 'Read More..'}
          </Text>
          <Divider style={{ backgroundColor: '#dfe6e9' }} />
          <View
            style={{ flexDirection: 'row', justifyContent: 'space-between' }}
          >
            <Text style={noteStyle}>{source.name.toUpperCase()}</Text>
            <Text style={noteStyle}>{time}</Text>
          </View>
        </Card>
      </TouchableHighlight>
    );
  }
}

const styles = {
  noteStyle: {
    margin: 5,
    fontStyle: 'italic',
    color: '#b2bec3',
    fontSize: 10
  },
};
```

##動作確認
```terminal:terminal
expo stert
```

最初に載せた画像のようになれば成功です。






参考記事：[How to build a news app with React Native](https://medium.freecodecamp.org/create-a-news-app-using-react-native-ced249263627)